mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-04 13:34:38 +08:00
Work on task #14494: Implement SO_BINDTODEVICE
TCP needs additional netif handling
This commit is contained in:
parent
c144e5b1ec
commit
5800cf51be
@ -272,7 +272,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
|||||||
|
|
||||||
/* don't call tcp_abort here: we must not deallocate the pcb since
|
/* don't call tcp_abort here: we must not deallocate the pcb since
|
||||||
that might not be expected when calling tcp_close */
|
that might not be expected when calling tcp_close */
|
||||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->local_port, pcb->remote_port);
|
pcb->local_port, pcb->remote_port);
|
||||||
|
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
@ -513,7 +513,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
|||||||
tcp_backlog_accepted(pcb);
|
tcp_backlog_accepted(pcb);
|
||||||
if (send_rst) {
|
if (send_rst) {
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||||
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
|
tcp_rst(pcb, seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
|
||||||
}
|
}
|
||||||
last_state = pcb->state;
|
last_state = pcb->state;
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
@ -920,24 +920,28 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
|||||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||||
pcb->remote_port = port;
|
pcb->remote_port = port;
|
||||||
|
|
||||||
/* check if we have a route to the remote host */
|
if (pcb->netif_idx != NETIF_NO_INDEX) {
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
netif = netif_get_by_index(pcb->netif_idx);
|
||||||
/* no local IP address set, yet. */
|
|
||||||
const ip_addr_t *local_ip;
|
|
||||||
ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
|
||||||
if ((netif == NULL) || (local_ip == NULL)) {
|
|
||||||
/* Don't even try to send a SYN packet if we have no route
|
|
||||||
since that will fail. */
|
|
||||||
return ERR_RTE;
|
|
||||||
}
|
|
||||||
/* Use the address as local address of the pcb. */
|
|
||||||
ip_addr_copy(pcb->local_ip, *local_ip);
|
|
||||||
} else {
|
} else {
|
||||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
/* check if we have a route to the remote host */
|
||||||
if (netif == NULL) {
|
if (ip_addr_isany(&pcb->local_ip)) {
|
||||||
/* Don't even try to send a SYN packet if we have no route
|
/* no local IP address set, yet. */
|
||||||
since that will fail. */
|
const ip_addr_t *local_ip;
|
||||||
return ERR_RTE;
|
ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
||||||
|
if ((netif == NULL) || (local_ip == NULL)) {
|
||||||
|
/* Don't even try to send a SYN packet if we have no route
|
||||||
|
since that will fail. */
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
/* Use the address as local address of the pcb. */
|
||||||
|
ip_addr_copy(pcb->local_ip, *local_ip);
|
||||||
|
} else {
|
||||||
|
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
||||||
|
if (netif == NULL) {
|
||||||
|
/* Don't even try to send a SYN packet if we have no route
|
||||||
|
since that will fail. */
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
@ -1213,8 +1217,8 @@ tcp_slowtmr_start:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pcb_reset) {
|
if (pcb_reset) {
|
||||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->local_port, pcb->remote_port);
|
pcb->local_port, pcb->remote_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
err_arg = pcb->callback_arg;
|
err_arg = pcb->callback_arg;
|
||||||
|
@ -224,6 +224,13 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||||
|
|
||||||
|
/* check if PCB is bound to specific netif */
|
||||||
|
if ((pcb->netif_idx != NETIF_NO_INDEX) &&
|
||||||
|
(pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (pcb->remote_port == tcphdr->src &&
|
if (pcb->remote_port == tcphdr->src &&
|
||||||
pcb->local_port == tcphdr->dest &&
|
pcb->local_port == tcphdr->dest &&
|
||||||
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
|
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
|
||||||
@ -250,6 +257,13 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
in the TIME-WAIT state. */
|
in the TIME-WAIT state. */
|
||||||
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||||
|
|
||||||
|
/* check if PCB is bound to specific netif */
|
||||||
|
if ((pcb->netif_idx != NETIF_NO_INDEX) &&
|
||||||
|
(pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (pcb->remote_port == tcphdr->src &&
|
if (pcb->remote_port == tcphdr->src &&
|
||||||
pcb->local_port == tcphdr->dest &&
|
pcb->local_port == tcphdr->dest &&
|
||||||
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
|
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
|
||||||
@ -516,14 +530,13 @@ aborted:
|
|||||||
inseg.p = NULL;
|
inseg.p = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* If no matching PCB was found, send a TCP RST (reset) to the
|
/* If no matching PCB was found, send a TCP RST (reset) to the
|
||||||
sender. */
|
sender. */
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
|
||||||
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
||||||
TCP_STATS_INC(tcp.proterr);
|
TCP_STATS_INC(tcp.proterr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
TCP_STATS_INC(tcp.drop);
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
tcp_rst(NULL, ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||||
}
|
}
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@ -565,7 +578,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
/* For incoming segments with the ACK flag set, respond with a
|
/* For incoming segments with the ACK flag set, respond with a
|
||||||
RST. */
|
RST. */
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
tcp_rst((const struct tcp_pcb*)pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||||
} else if (flags & TCP_SYN) {
|
} else if (flags & TCP_SYN) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||||
@ -611,6 +624,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
|
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
|
||||||
/* inherit socket options */
|
/* inherit socket options */
|
||||||
npcb->so_options = pcb->so_options & SOF_INHERITED;
|
npcb->so_options = pcb->so_options & SOF_INHERITED;
|
||||||
|
npcb->netif_idx = pcb->netif_idx;
|
||||||
/* Register the new PCB so that we can begin receiving segments
|
/* Register the new PCB so that we can begin receiving segments
|
||||||
for it. */
|
for it. */
|
||||||
TCP_REG_ACTIVE(npcb);
|
TCP_REG_ACTIVE(npcb);
|
||||||
@ -663,7 +677,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
|||||||
should be sent in reply */
|
should be sent in reply */
|
||||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||||
/* If the SYN is in the window it is an error, send a reset */
|
/* If the SYN is in the window it is an error, send a reset */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -813,7 +827,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
/* received ACK? possibly a half-open connection */
|
/* received ACK? possibly a half-open connection */
|
||||||
else if (flags & TCP_ACK) {
|
else if (flags & TCP_ACK) {
|
||||||
/* send a RST to bring the other side in a non-synchronized state. */
|
/* send a RST to bring the other side in a non-synchronized state. */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||||
/* Resend SYN immediately (don't wait for rto timeout) to establish
|
/* Resend SYN immediately (don't wait for rto timeout) to establish
|
||||||
connection faster, but do not send more SYNs than we otherwise would
|
connection faster, but do not send more SYNs than we otherwise would
|
||||||
@ -873,7 +887,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* incorrect ACK number, send RST */
|
/* incorrect ACK number, send RST */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||||
}
|
}
|
||||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||||
|
@ -94,6 +94,15 @@
|
|||||||
/* Forward declarations.*/
|
/* Forward declarations.*/
|
||||||
static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif);
|
static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif);
|
||||||
|
|
||||||
|
static struct netif* tcp_route(const struct tcp_pcb *pcb, const ip_addr_t *src, const ip_addr_t *dst)
|
||||||
|
{
|
||||||
|
if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) {
|
||||||
|
return netif_get_by_index(pcb->netif_idx);
|
||||||
|
} else {
|
||||||
|
return ip_route(src, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Allocate a pbuf and create a tcphdr at p->payload, used for output
|
/** Allocate a pbuf and create a tcphdr at p->payload, used for output
|
||||||
* functions other than the default tcp_output -> tcp_output_segment
|
* functions other than the default tcp_output -> tcp_output_segment
|
||||||
* (e.g. tcp_send_empty_ack, etc.)
|
* (e.g. tcp_send_empty_ack, etc.)
|
||||||
@ -959,7 +968,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
err = ERR_RTE;
|
err = ERR_RTE;
|
||||||
} else {
|
} else {
|
||||||
@ -1040,7 +1049,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
for (; useg->next != NULL; useg = useg->next);
|
for (; useg->next != NULL; useg = useg->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
return ERR_RTE;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
@ -1339,6 +1348,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
|
|||||||
* tcp_rst() has a number of arguments that are taken from a tcp_pcb for
|
* tcp_rst() has a number of arguments that are taken from a tcp_pcb for
|
||||||
* most other segment output functions.
|
* most other segment output functions.
|
||||||
*
|
*
|
||||||
|
* @param pcb TCP pcb
|
||||||
* @param seqno the sequence number to use for the outgoing segment
|
* @param seqno the sequence number to use for the outgoing segment
|
||||||
* @param ackno the acknowledge number to use for the outgoing segment
|
* @param ackno the acknowledge number to use for the outgoing segment
|
||||||
* @param local_ip the local IP address to send the segment from
|
* @param local_ip the local IP address to send the segment from
|
||||||
@ -1347,7 +1357,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
|
|||||||
* @param remote_port the remote TCP port to send the segment to
|
* @param remote_port the remote TCP port to send the segment to
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
tcp_rst(u32_t seqno, u32_t ackno,
|
tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno,
|
||||||
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
||||||
u16_t local_port, u16_t remote_port)
|
u16_t local_port, u16_t remote_port)
|
||||||
{
|
{
|
||||||
@ -1379,7 +1389,7 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
|||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
MIB2_STATS_INC(mib2.tcpoutrsts);
|
MIB2_STATS_INC(mib2.tcpoutrsts);
|
||||||
|
|
||||||
netif = ip_route(local_ip, remote_ip);
|
netif = tcp_route(pcb, local_ip, remote_ip);
|
||||||
if (netif != NULL) {
|
if (netif != NULL) {
|
||||||
#if CHECKSUM_GEN_TCP
|
#if CHECKSUM_GEN_TCP
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
|
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
|
||||||
@ -1559,7 +1569,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
("tcp_keepalive: could not allocate memory for pbuf\n"));
|
("tcp_keepalive: could not allocate memory for pbuf\n"));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
err = ERR_RTE;
|
err = ERR_RTE;
|
||||||
} else {
|
} else {
|
||||||
@ -1653,7 +1663,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
pcb->snd_nxt = snd_nxt;
|
pcb->snd_nxt = snd_nxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
err = ERR_RTE;
|
err = ERR_RTE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -451,7 +451,7 @@ err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
|
|||||||
|
|
||||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||||
|
|
||||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
void tcp_rst(const struct tcp_pcb* pcb, u32_t seqno, u32_t ackno,
|
||||||
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
||||||
u16_t local_port, u16_t remote_port);
|
u16_t local_port, u16_t remote_port);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user