Skip to content

Instantly share code, notes, and snippets.

@wongsyrone
Last active April 24, 2020 07:42
Show Gist options
  • Save wongsyrone/2a2c134e8f927364e598d2a6e706f4a8 to your computer and use it in GitHub Desktop.
Save wongsyrone/2a2c134e8f927364e598d2a6e706f4a8 to your computer and use it in GitHub Desktop.
badvpn change to Lwip 1.4(.1 maybe)
diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c
index 4b38999c..1acc2558 100644
--- a/src/core/ipv4/ip4.c
+++ b/src/core/ipv4/ip4.c
@@ -473,6 +473,12 @@ ip_input(struct pbuf *p, struct netif *inp)
}
}
+ /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it
+ isn't for a local address */
+ if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IPH_PROTO(iphdr) == IP_PROTO_TCP) {
+ netif = inp;
+ }
+
/* packet not for us? */
if (netif == NULL) {
/* packet not for us, route or discard */
diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c
index 94e423a2..1eb91f96 100644
--- a/src/core/ipv6/ip6.c
+++ b/src/core/ipv6/ip6.c
@@ -477,6 +477,12 @@ netif_found:
IP6_STATS_INC(ip6.drop);
goto ip6_input_cleanup;
}
+
+ /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it
+ isn't for a local address */
+ if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IP6H_NEXTH(ip6hdr) == IP6_NEXTH_TCP) {
+ netif = inp;
+ }
/* packet not for us? */
if (netif == NULL) {
diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c
index 44629dbe..513db985 100644
--- a/src/core/ipv6/nd6.c
+++ b/src/core/ipv6/nd6.c
@@ -621,7 +621,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
void
nd6_tmr(void)
{
- s8_t i, j;
+ s8_t i;
+#if LWIP_IPV6_AUTOCONFIG
+ s8_t j;
+#endif
struct netif * netif;
/* Process neighbor entries. */
@@ -1397,7 +1400,9 @@ nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif)
/* Found empty prefix entry. */
prefix_list[i].netif = netif;
ip6_addr_set(&(prefix_list[i].prefix), prefix);
+#if LWIP_IPV6_AUTOCONFIG
prefix_list[i].flags = 0;
+#endif
return i;
}
}
diff --git a/src/core/netif.c b/src/core/netif.c
index f8133f76..dcc87580 100644
--- a/src/core/netif.c
+++ b/src/core/netif.c
@@ -349,6 +349,13 @@ netif_find(char *name)
return NULL;
}
+int netif_is_named (struct netif *netif, const char name[3])
+{
+ u8_t num = name[2] - '0';
+
+ return (!memcmp(netif->name, name, 2) && netif->num == num);
+}
+
/**
* Change the IP address of a network interface
*
@@ -435,6 +442,15 @@ netif_set_gw(struct netif *netif, ip_addr_t *gw)
ip4_addr4_16(&netif->gw)));
}
+void netif_set_pretend_tcp (struct netif *netif, u8_t pretend)
+{
+ if (pretend) {
+ netif->flags |= NETIF_FLAG_PRETEND_TCP;
+ } else {
+ netif->flags &= ~NETIF_FLAG_PRETEND_TCP;
+ }
+}
+
/**
* Change the netmask of a network interface
*
@@ -842,7 +858,7 @@ netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr)
void
netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit)
{
- u8_t i, addr_index;
+ u8_t i, addr_index, min_len;
/* Link-local prefix. */
netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul);
@@ -865,8 +881,9 @@ netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit)
netif->ip6_addr[0].addr[2] = 0;
netif->ip6_addr[0].addr[3] = 0;
+ min_len = netif->hwaddr_len < 8 ? netif->hwaddr_len : 8;
addr_index = 3;
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < min_len; i++) {
if (i == 4) {
addr_index--;
}
diff --git a/src/core/tcp.c b/src/core/tcp.c
index a0cbb159..55496d05 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -209,7 +209,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
* is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */
err = ERR_OK;
- if (pcb->local_port != 0) {
+ if (pcb->local_port != 0 || pcb->bound_to_netif) {
TCP_RMV(&tcp_bound_pcbs, pcb);
}
memp_free(MEMP_TCP_PCB, pcb);
@@ -484,6 +484,7 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
}
}
+ pcb->bound_to_netif = 0;
if (!ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr))) {
ipX_addr_set(PCB_ISIPV6(pcb), &pcb->local_ip, ip_2_ipX(ipaddr));
}
@@ -492,6 +493,32 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
return ERR_OK;
}
+
+err_t
+tcp_bind_to_netif(struct tcp_pcb *pcb, const char ifname[3])
+{
+ LWIP_ERROR("tcp_bind_if: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
+
+ /* Check if the interface is already in use */
+ for (int i = 0; i < NUM_TCP_PCB_LISTS; i++) {
+ for(struct tcp_pcb *cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
+ if (IP_PCB_IPVER_EQ(pcb, cpcb) &&
+ cpcb->bound_to_netif &&
+ !memcmp(cpcb->local_netif, ifname, sizeof(cpcb->local_netif))) {
+ return ERR_USE;
+ }
+ }
+ }
+
+ pcb->bound_to_netif = 1;
+ ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->local_ip);
+ pcb->local_port = 0;
+ memcpy(pcb->local_netif, ifname, sizeof(pcb->local_netif));
+ TCP_REG(&tcp_bound_pcbs, pcb);
+ LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind_to_netif: bind to interface %c%c%c\n", ifname[0], ifname[1], ifname[2]));
+ return ERR_OK;
+}
+
#if LWIP_CALLBACK_API
/**
* Default accept callback if no accept callback is specified by the user.
@@ -534,7 +561,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
return pcb;
}
#if SO_REUSE
- if (ip_get_option(pcb, SOF_REUSEADDR)) {
+ if (ip_get_option(pcb, SOF_REUSEADDR) && !pcb->have_local_netif) {
/* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
is declared (listen-/connection-pcb), we have to make sure now that
this port is only used once for every local IP. */
@@ -554,7 +581,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
return NULL;
}
lpcb->callback_arg = pcb->callback_arg;
+ lpcb->bound_to_netif = pcb->bound_to_netif;
lpcb->local_port = pcb->local_port;
+ memcpy(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif));
lpcb->state = LISTEN;
lpcb->prio = pcb->prio;
lpcb->so_options = pcb->so_options;
@@ -566,7 +595,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
lpcb->accept_any_ip_version = 0;
#endif /* LWIP_IPV6 */
ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip);
- if (pcb->local_port != 0) {
+ if (pcb->local_port != 0 || pcb->bound_to_netif) {
TCP_RMV(&tcp_bound_pcbs, pcb);
}
memp_free(MEMP_TCP_PCB, pcb);
@@ -722,6 +751,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
u16_t old_local_port;
LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
+ LWIP_ERROR("tcp_connect: cannot connect pcb bound to netif", !pcb->bound_to_netif, return ERR_VAL);
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
if (ipaddr != NULL) {
@@ -1536,16 +1566,19 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
tcp_listen_pcbs.listen_pcbs != NULL);
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
- if ((lpcb->local_port == pcb->local_port) &&
- IP_PCB_IPVER_EQ(pcb, lpcb) &&
- (ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) ||
- ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) {
+ if ((!lpcb->bound_to_netif && !pcb->bound_to_netif &&
+ (lpcb->local_port == pcb->local_port) &&
+ IP_PCB_IPVER_EQ(pcb, lpcb) &&
+ (ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) ||
+ ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) ||
+ (lpcb->bound_to_netif && pcb->bound_to_netif &&
+ !memcmp(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif)))) {
/* port and address of the listen pcb match the timed-out pcb */
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
lpcb->accepts_pending > 0);
lpcb->accepts_pending--;
break;
- }
+ }
}
}
#endif /* TCP_LISTEN_BACKLOG */
diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
index dacf5cf9..6c382d06 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -219,8 +219,16 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Finally, if we still did not get a match, we check all PCBs that
are LISTENing for incoming connections. */
prev = NULL;
+ struct tcp_pcb_listen *netif_pcb = NULL;
+ struct tcp_pcb *netif_pcb_prev = NULL;
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
- if (lpcb->local_port == tcphdr->dest) {
+ if (lpcb->bound_to_netif) {
+ if (IP_PCB_IPVER_INPUT_MATCH(lpcb) && netif_is_named(inp, lpcb->local_netif)) {
+ netif_pcb = lpcb;
+ netif_pcb_prev = prev;
+ }
+ }
+ else if (lpcb->local_port == tcphdr->dest) {
#if LWIP_IPV6
if (lpcb->accept_any_ip_version) {
/* found an ANY-match */
@@ -257,6 +265,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
prev = lpcb_prev;
}
#endif /* SO_REUSE */
+ if (lpcb == NULL && netif_pcb) {
+ lpcb = netif_pcb;
+ prev = netif_pcb_prev;
+ }
if (lpcb != NULL) {
/* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment
@@ -495,7 +507,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
#endif /* LWIP_IPV6 */
ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr());
ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr());
- npcb->local_port = pcb->local_port;
+ npcb->bound_to_netif = pcb->bound_to_netif;
+ npcb->local_port = tcphdr->dest;
+ memcpy(npcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif));
npcb->remote_port = tcphdr->src;
npcb->state = SYN_RCVD;
npcb->rcv_nxt = seqno + 1;
diff --git a/src/include/lwip/arch.h b/src/include/lwip/arch.h
index 4d6df773..101a7530 100644
--- a/src/include/lwip/arch.h
+++ b/src/include/lwip/arch.h
@@ -32,6 +32,8 @@
#ifndef __LWIP_ARCH_H__
#define __LWIP_ARCH_H__
+#include "arch/cc.h"
+
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
@@ -40,8 +42,6 @@
#define BIG_ENDIAN 4321
#endif
-#include "arch/cc.h"
-
/** Temporary: define format string for size_t if not defined in cc.h */
#ifndef SZT_F
#define SZT_F U32_F
diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h
index 322d2d0e..f9770324 100644
--- a/src/include/lwip/netif.h
+++ b/src/include/lwip/netif.h
@@ -97,6 +97,9 @@ extern "C" {
/** If set, the netif has IGMP capability.
* Set by the netif driver in its init function. */
#define NETIF_FLAG_IGMP 0x80U
+/** Whether to pretend that we are every host for TCP packets.
+ * Set by netif_set_pretend_tcp. */
+#define NETIF_FLAG_PRETEND_TCP 0x100U
/** Function prototype for netif init functions. Set up flags and output/linkoutput
* callback functions in this function.
@@ -235,7 +238,7 @@ struct netif {
/** link level hardware address of this interface */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
/** flags (see NETIF_FLAG_ above) */
- u8_t flags;
+ u16_t flags;
/** descriptive abbreviation */
char name[2];
/** number of this interface */
@@ -321,11 +324,14 @@ void netif_remove(struct netif * netif);
structure. */
struct netif *netif_find(char *name);
+int netif_is_named (struct netif *netif, const char name[3]);
+
void netif_set_default(struct netif *netif);
void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr);
void netif_set_netmask(struct netif *netif, ip_addr_t *netmask);
void netif_set_gw(struct netif *netif, ip_addr_t *gw);
+void netif_set_pretend_tcp(struct netif *netif, u8_t pretend);
void netif_set_up(struct netif *netif);
void netif_set_down(struct netif *netif);
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
index 0ab301f0..535b6a38 100644
--- a/src/include/lwip/tcp.h
+++ b/src/include/lwip/tcp.h
@@ -163,7 +163,9 @@ enum tcp_state {
enum tcp_state state; /* TCP state */ \
u8_t prio; \
/* ports are in host byte order */ \
- u16_t local_port
+ int bound_to_netif; \
+ u16_t local_port; \
+ char local_netif[3]
/* the TCP protocol control block */
@@ -346,6 +348,7 @@ void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
u16_t port);
+err_t tcp_bind_to_netif (struct tcp_pcb *pcb, const char ifname[3]);
err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
u16_t port, tcp_connected_fn connected);
diff --git a/src/include/netif/etharp.h b/src/include/netif/etharp.h
index 92d57ae4..8275a28f 100644
--- a/src/include/netif/etharp.h
+++ b/src/include/netif/etharp.h
@@ -214,10 +214,10 @@ err_t ethernet_input(struct pbuf *p, struct netif *netif);
extern const struct eth_addr ethbroadcast, ethzero;
-#endif /* LWIP_ARP || LWIP_ETHERNET */
-
#ifdef __cplusplus
}
#endif
+#endif /* LWIP_ARP || LWIP_ETHERNET */
+
#endif /* __NETIF_ARP_H__ */
@wongsyrone
Copy link
Author

wongsyrone commented Sep 15, 2017

And a patch for lwip 1710fc1a89578dfaaff684a1aafbc4d16e346f79 and later

diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c
index cdba4c8..2835fae 100644
--- a/src/core/ipv4/ip4.c
+++ b/src/core/ipv4/ip4.c
@@ -208,8 +208,10 @@ ip4_route(const ip4_addr_t *dest)
 #endif
 #endif /* !LWIP_SINGLE_NETIF */
 
-  if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||
-      ip4_addr_isany_val(*netif_ip4_addr(netif_default))) {
+  if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)
+      /* Yes we are binding to any addr */
+      // || ip4_addr_isany_val(*netif_ip4_addr(netif_default))
+  ) {
     /* No matching netif found and default netif is not usable.
        If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */
     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
@@ -598,6 +600,12 @@ ip4_input(struct pbuf *p, struct netif *inp)
     }
   }
 
+  /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it
+     isn't for a local address */
+  if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IPH_PROTO(iphdr) == IP_PROTO_TCP) {
+      netif = inp;
+  }
+
   /* packet not for us? */
   if (netif == NULL) {
     /* packet not for us, route or discard */
diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c
index 90bf5b0..d65de89 100644
--- a/src/core/ipv6/ip6.c
+++ b/src/core/ipv6/ip6.c
@@ -670,6 +670,12 @@ netif_found:
     goto ip6_input_cleanup;
   }
 
+  /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it
+     isn't for a local address */
+  if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IP6H_NEXTH(ip6hdr) == IP6_NEXTH_TCP) {
+      netif = inp;
+  }
+
   /* packet not for us? */
   if (netif == NULL) {
     /* packet not for us, route or discard */
diff --git a/src/core/netif.c b/src/core/netif.c
index 3e9f399..2100bf9 100644
--- a/src/core/netif.c
+++ b/src/core/netif.c
@@ -657,6 +657,15 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
   }
 }
 
+void netif_set_pretend_tcp (struct netif *netif, u8_t pretend)
+{
+    if (pretend) {
+        netif->flags |= NETIF_FLAG_PRETEND_TCP;
+    } else {
+        netif->flags &= ~NETIF_FLAG_PRETEND_TCP;
+    }
+}
+
 /**
  * @ingroup netif_ip4
  * Change the netmask of a network interface
@@ -697,6 +706,13 @@ netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
 }
 #endif /* LWIP_IPV4 */
 
+int netif_is_named (struct netif *netif, const char name[3])
+{
+    u8_t num = name[2] - '0';
+
+    return (!memcmp(netif->name, name, 2) && netif->num == num);
+}
+
 /**
  * @ingroup netif
  * Set a network interface as the default network interface
diff --git a/src/core/tcp.c b/src/core/tcp.c
index bf21a06..610ff66 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -306,7 +306,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
        * or for a pcb that has been used and then entered the CLOSED state
        * is erroneous, but this should never happen as the pcb has in those cases
        * been freed, and so any remaining handles are bogus. */
-      if (pcb->local_port != 0) {
+      if (pcb->local_port != 0 || pcb->bound_to_netif) {
         TCP_RMV(&tcp_bound_pcbs, pcb);
       }
       memp_free(MEMP_TCP_PCB, pcb);
@@ -637,6 +637,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
     }
   }
 
+  pcb->bound_to_netif = 0;
   if (!ip_addr_isany(ipaddr)) {
     ip_addr_set(&pcb->local_ip, ipaddr);
   }
@@ -646,6 +647,38 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
   return ERR_OK;
 }
 
+err_t
+tcp_bind_to_netif(struct tcp_pcb *pcb, const char ifname[3])
+{
+  int i;
+  struct tcp_pcb *cpcb;
+  
+  LWIP_ERROR("tcp_bind_to_netif: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL);
+
+  /* Check if the interface is already in use (in tcp_listen_pcbs and tcp_bound_pcbs) */
+  for (i = 0; i < 2; i++) {
+    for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
+      if (cpcb->bound_to_netif &&
+          !memcmp(cpcb->local_netif, ifname, sizeof(cpcb->local_netif)) && (
+            IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_IS_ANY_TYPE_VAL(cpcb->local_ip) ||
+            IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(&cpcb->local_ip))) {
+        return ERR_USE;
+      }
+    }
+  }
+
+  pcb->bound_to_netif = 1;
+  if (!IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
+    ip_addr_set_any(IP_IS_V6(&pcb->local_ip), &pcb->local_ip);
+  }
+  pcb->local_port = 0;
+  memcpy(pcb->local_netif, ifname, sizeof(pcb->local_netif));
+  TCP_REG(&tcp_bound_pcbs, pcb);
+  LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind_to_netif: bind to interface %c%c%c\n", ifname[0], ifname[1], ifname[2]));
+  // should call tcp_bind_netif() to set pcb->netif_idx
+  return ERR_OK;
+}
+
 /**
  * @ingroup tcp_raw
  * Binds the connection to a netif and IP address.
@@ -735,7 +768,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
     goto done;
   }
 #if SO_REUSE
-  if (ip_get_option(pcb, SOF_REUSEADDR)) {
+  if (ip_get_option(pcb, SOF_REUSEADDR) && !pcb->have_local_netif) {
     /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
        is declared (listen-/connection-pcb), we have to make sure now that
        this port is only used once for every local IP. */
@@ -756,7 +789,9 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
     goto done;
   }
   lpcb->callback_arg = pcb->callback_arg;
+  lpcb->bound_to_netif = pcb->bound_to_netif;
   lpcb->local_port = pcb->local_port;
+  memcpy(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif));
   lpcb->state = LISTEN;
   lpcb->prio = pcb->prio;
   lpcb->so_options = pcb->so_options;
@@ -767,7 +802,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
   IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type);
 #endif /* LWIP_IPV4 && LWIP_IPV6 */
   ip_addr_copy(lpcb->local_ip, pcb->local_ip);
-  if (pcb->local_port != 0) {
+  if (pcb->local_port != 0 || pcb->bound_to_netif) {
     TCP_RMV(&tcp_bound_pcbs, pcb);
   }
   memp_free(MEMP_TCP_PCB, pcb);
@@ -927,6 +962,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
   }
 
   LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
+  LWIP_ERROR("tcp_connect: cannot connect pcb bound to netif", !pcb->bound_to_netif, return ERR_VAL);
 
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
   ip_addr_set(&pcb->remote_ip, ipaddr);
diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
index f9f53e5..c4ee51d 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -303,6 +303,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
     /* Finally, if we still did not get a match, we check all PCBs that
        are LISTENing for incoming connections. */
     prev = NULL;
+    struct tcp_pcb_listen *netif_pcb = NULL;
+    struct tcp_pcb *netif_pcb_prev = NULL;
     for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
       /* check if PCB is bound to specific netif */
       if ((lpcb->netif_idx != NETIF_NO_INDEX) &&
@@ -311,7 +313,15 @@ tcp_input(struct pbuf *p, struct netif *inp)
         continue;
       }
 
-      if (lpcb->local_port == tcphdr->dest) {
+      if (lpcb->bound_to_netif) {
+        if (IP_ADDR_PCB_VERSION_MATCH(lpcb, ip_current_dest_addr()) &&
+            netif_is_named(inp, lpcb->local_netif)) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_input: found lpcb->bound_to_netif, set netif_pcb(_prev)\n"));
+          netif_pcb = lpcb;
+          netif_pcb_prev = prev;
+        }
+      }
+      else if (lpcb->local_port == tcphdr->dest) {
         if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) {
           /* found an ANY TYPE (IPv4/IPv6) match */
 #if SO_REUSE
@@ -345,6 +355,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
       prev = lpcb_prev;
     }
 #endif /* SO_REUSE */
+    if (lpcb == NULL && netif_pcb) {
+        lpcb = netif_pcb;
+        prev = netif_pcb_prev;
+    }
     if (lpcb != NULL) {
       /* Move this PCB to the front of the list so that subsequent
          lookups will be faster (we exploit locality in TCP segment
@@ -646,7 +660,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
     /* Set up the new PCB. */
     ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
     ip_addr_copy(npcb->remote_ip, *ip_current_src_addr());
-    npcb->local_port = pcb->local_port;
+    /* npcb->bound_to_netif is 0 regardless of lpcb */
+    npcb->local_port = tcphdr->dest;
     npcb->remote_port = tcphdr->src;
     npcb->state = SYN_RCVD;
     npcb->rcv_nxt = seqno + 1;
diff --git a/src/include/lwip/arch.h b/src/include/lwip/arch.h
index 16a6e6c..56f5425 100644
--- a/src/include/lwip/arch.h
+++ b/src/include/lwip/arch.h
@@ -37,6 +37,8 @@
 #ifndef LWIP_HDR_ARCH_H
 #define LWIP_HDR_ARCH_H
 
+#include "arch/cc.h"
+
 #ifndef LITTLE_ENDIAN
 #define LITTLE_ENDIAN 1234
 #endif
@@ -45,8 +47,6 @@
 #define BIG_ENDIAN 4321
 #endif
 
-#include "arch/cc.h"
-
 /**
  * @defgroup compiler_abstraction Compiler/platform abstraction
  * @ingroup sys_layer
diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h
index 6b302bf..f552708 100644
--- a/src/include/lwip/netif.h
+++ b/src/include/lwip/netif.h
@@ -105,6 +105,9 @@ extern "C" {
 /** If set, the netif has MLD6 capability.
  * Set by the netif driver in its init function. */
 #define NETIF_FLAG_MLD6         0x40U
+/** Whether to pretend that we are every host for TCP packets.
+ * Set by netif_set_pretend_tcp. */
+#define NETIF_FLAG_PRETEND_TCP  0x100U
 
 /**
  * @}
@@ -318,7 +321,7 @@ struct netif {
   /** number of bytes used in hwaddr */
   u8_t hwaddr_len;
   /** flags (@see @ref netif_flags) */
-  u8_t flags;
+  u16_t flags;
   /** descriptive abbreviation */
   char name[2];
   /** number of this interface. Used for @ref if_api and @ref netifapi_netif, 
@@ -405,12 +408,15 @@ void netif_remove(struct netif * netif);
    structure. */
 struct netif *netif_find(const char *name);
 
+int netif_is_named (struct netif *netif, const char name[3]);
+
 void netif_set_default(struct netif *netif);
 
 #if LWIP_IPV4
 void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr);
 void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask);
 void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
+void netif_set_pretend_tcp(struct netif *netif, u8_t pretend);
 /** @ingroup netif_ip4 */
 #define netif_ip4_addr(netif)    ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr)))
 /** @ingroup netif_ip4 */
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
index aa07920..9a7fd32 100644
--- a/src/include/lwip/tcp.h
+++ b/src/include/lwip/tcp.h
@@ -174,6 +174,8 @@ typedef u16_t tcpflags_t;
   enum tcp_state state; /* TCP state */ \
   u8_t prio; \
   /* ports are in host byte order */ \
+  u8_t bound_to_netif; \
+  char local_netif[3]; \
   u16_t local_port
 
 
@@ -416,6 +418,7 @@ void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
 err_t            tcp_bind    (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
                               u16_t port);
 void             tcp_bind_netif(struct tcp_pcb *pcb, const struct netif *netif);
+err_t            tcp_bind_to_netif (struct tcp_pcb *pcb, const char ifname[3]);
 err_t            tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
                               u16_t port, tcp_connected_fn connected);
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment