Work on task #14494: Implement SO_BINDTODEVICE

TCP needs additional netif handling
This commit is contained in:
Dirk Ziegelmeier 2017-05-03 08:00:06 +02:00
parent c144e5b1ec
commit 5800cf51be
4 changed files with 62 additions and 34 deletions

View File

@ -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;

View File

@ -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)) {

View File

@ -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 {

View File

@ -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);