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
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);
tcp_pcb_purge(pcb);
@ -513,7 +513,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
tcp_backlog_accepted(pcb);
if (send_rst) {
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;
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);
pcb->remote_port = port;
/* check if we have a route to the remote host */
if (ip_addr_isany(&pcb->local_ip)) {
/* 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);
if (pcb->netif_idx != NETIF_NO_INDEX) {
netif = netif_get_by_index(pcb->netif_idx);
} 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;
/* check if we have a route to the remote host */
if (ip_addr_isany(&pcb->local_ip)) {
/* 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 {
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);
@ -1213,8 +1217,8 @@ tcp_slowtmr_start:
}
if (pcb_reset) {
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
pcb->local_port, pcb->remote_port);
tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
pcb->local_port, pcb->remote_port);
}
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 != TIME-WAIT", pcb->state != TIME_WAIT);
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 &&
pcb->local_port == tcphdr->dest &&
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. */
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
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 &&
pcb->local_port == tcphdr->dest &&
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
@ -516,14 +530,13 @@ aborted:
inseg.p = NULL;
}
} else {
/* If no matching PCB was found, send a TCP RST (reset) to the
sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
TCP_STATS_INC(tcp.proterr);
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);
}
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
RST. */
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);
} else if (flags & TCP_SYN) {
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 */
/* inherit socket options */
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
for it. */
TCP_REG_ACTIVE(npcb);
@ -663,7 +677,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
should be sent in reply */
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 */
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);
return;
}
@ -813,7 +827,7 @@ tcp_process(struct tcp_pcb *pcb)
/* received ACK? possibly a half-open connection */
else if (flags & TCP_ACK) {
/* 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);
/* Resend SYN immediately (don't wait for rto timeout) to establish
connection faster, but do not send more SYNs than we otherwise would
@ -873,7 +887,7 @@ tcp_process(struct tcp_pcb *pcb)
}
} else {
/* 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);
}
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {

View File

@ -94,6 +94,15 @@
/* Forward declarations.*/
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
* functions other than the default tcp_output -> tcp_output_segment
* (e.g. tcp_send_empty_ack, etc.)
@ -959,7 +968,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
}
#endif
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
if (netif == NULL) {
err = ERR_RTE;
} else {
@ -1040,7 +1049,7 @@ tcp_output(struct tcp_pcb *pcb)
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) {
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
* most other segment output functions.
*
* @param pcb TCP pcb
* @param seqno the sequence 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
@ -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
*/
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,
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);
MIB2_STATS_INC(mib2.tcpoutrsts);
netif = ip_route(local_ip, remote_ip);
netif = tcp_route(pcb, local_ip, remote_ip);
if (netif != NULL) {
#if 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"));
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) {
err = ERR_RTE;
} else {
@ -1653,7 +1663,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
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) {
err = ERR_RTE;
} 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_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,
u16_t local_port, u16_t remote_port);