Browse Source

lwip: add option to allow accepting TCP connections not destined to a local address

ambrop7 15 years ago
parent
commit
f46086d2cc

+ 6 - 0
lwip/src/core/ipv4/ip.c

@@ -414,6 +414,12 @@ ip_input(struct pbuf *p, struct netif *inp)
       return ERR_OK;
       return ERR_OK;
     }
     }
   }
   }
+  
+  /* 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? */
   /* packet not for us? */
   if (netif == NULL) {
   if (netif == NULL) {

+ 16 - 0
lwip/src/core/netif.c

@@ -306,6 +306,13 @@ netif_find(char *name)
   return NULL;
   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
  * Change the IP address of a network interface
  *
  *
@@ -392,6 +399,15 @@ netif_set_gw(struct netif *netif, ip_addr_t *gw)
     ip4_addr4_16(&netif->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
  * Change the netmask of a network interface
  *
  *

+ 40 - 4
lwip/src/core/tcp.c

@@ -441,6 +441,7 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
     }
     }
   }
   }
 
 
+  pcb->bound_to_netif = 0;
   if (!ip_addr_isany(ipaddr)) {
   if (!ip_addr_isany(ipaddr)) {
     pcb->local_ip = *ipaddr;
     pcb->local_ip = *ipaddr;
   }
   }
@@ -449,6 +450,30 @@ 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));
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
   return ERR_OK;
   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 (cpcb->bound_to_netif && !memcmp(cpcb->local_netif, ifname, sizeof(ifname))) {
+                return ERR_USE;
+            }
+        }
+    }
+    
+    pcb->bound_to_netif = 1;
+    ip_addr_set_any(&pcb->local_ip);
+    pcb->local_port = 0;
+    memcpy(pcb->local_netif, ifname, sizeof(ifname));
+    TCP_REG(&tcp_bound_pcbs, pcb);
+    LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind_if: bind to interface %s", ifname));
+    return ERR_OK;
+}
+
 #if LWIP_CALLBACK_API
 #if LWIP_CALLBACK_API
 /**
 /**
  * Default accept callback if no accept callback is specified by the user.
  * Default accept callback if no accept callback is specified by the user.
@@ -491,7 +516,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
     return pcb;
     return pcb;
   }
   }
 #if SO_REUSE
 #if SO_REUSE
-  if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+  if ((pcb->so_options & SOF_REUSEADDR) != 0 && !pcb->have_local_netif) {
     /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
     /* 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
        is declared (listen-/connection-pcb), we have to make sure now that
        this port is only used once for every local IP. */
        this port is only used once for every local IP. */
@@ -510,7 +535,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
     return NULL;
     return NULL;
   }
   }
   lpcb->callback_arg = pcb->callback_arg;
   lpcb->callback_arg = pcb->callback_arg;
+  lpcb->bound_to_netif = pcb->bound_to_netif;
   lpcb->local_port = pcb->local_port;
   lpcb->local_port = pcb->local_port;
+  memcpy(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif));
   lpcb->state = LISTEN;
   lpcb->state = LISTEN;
   lpcb->prio = pcb->prio;
   lpcb->prio = pcb->prio;
   lpcb->so_options = pcb->so_options;
   lpcb->so_options = pcb->so_options;
@@ -1364,9 +1391,18 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
       LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
       LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
         tcp_listen_pcbs.listen_pcbs != NULL);
         tcp_listen_pcbs.listen_pcbs != NULL);
       for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
       for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
-        if ((lpcb->local_port == pcb->local_port) &&
-            (ip_addr_isany(&lpcb->local_ip) ||
-             ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
+        if (
+          (
+            !lpcb->bound_to_netif && !pcb->bound_to_netif &&
+            lpcb->local_port == pcb->local_port && (
+              ip_addr_isany(&lpcb->local_ip) ||
+              ip_addr_cmp(&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 */
             /* port and address of the listen pcb match the timed-out pcb */
             LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
             LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
               lpcb->accepts_pending > 0);
               lpcb->accepts_pending > 0);

+ 16 - 2
lwip/src/core/tcp_in.c

@@ -225,8 +225,16 @@ tcp_input(struct pbuf *p, struct netif *inp)
     /* Finally, if we still did not get a match, we check all PCBs that
     /* Finally, if we still did not get a match, we check all PCBs that
        are LISTENing for incoming connections. */
        are LISTENing for incoming connections. */
     prev = NULL;
     prev = NULL;
+    struct tcp_pcb_listen *netif_pcb = NULL;
+    struct tcp_pcb *netif_pcb_prev;
     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
-      if (lpcb->local_port == tcphdr->dest) {
+      if (lpcb->bound_to_netif) {
+        if (netif_is_named(inp, lpcb->local_netif)) {
+          netif_pcb = lpcb;
+          netif_pcb_prev = prev;
+        }
+      }
+      else if (lpcb->local_port == tcphdr->dest) {
 #if SO_REUSE
 #if SO_REUSE
         if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
         if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
           /* found an exact match */
           /* found an exact match */
@@ -254,6 +262,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
       prev = lpcb_prev;
       prev = lpcb_prev;
     }
     }
 #endif /* SO_REUSE */
 #endif /* SO_REUSE */
+    if (lpcb == NULL && netif_pcb) {
+        lpcb = netif_pcb;
+        prev = netif_pcb_prev;
+    }
     if (lpcb != NULL) {
     if (lpcb != NULL) {
       /* Move this PCB to the front of the list so that subsequent
       /* Move this PCB to the front of the list so that subsequent
          lookups will be faster (we exploit locality in TCP segment
          lookups will be faster (we exploit locality in TCP segment
@@ -474,7 +486,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
 #endif /* TCP_LISTEN_BACKLOG */
 #endif /* TCP_LISTEN_BACKLOG */
     /* Set up the new PCB. */
     /* Set up the new PCB. */
     ip_addr_copy(npcb->local_ip, current_iphdr_dest);
     ip_addr_copy(npcb->local_ip, current_iphdr_dest);
-    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));
     ip_addr_copy(npcb->remote_ip, current_iphdr_src);
     ip_addr_copy(npcb->remote_ip, current_iphdr_src);
     npcb->remote_port = tcphdr->src;
     npcb->remote_port = tcphdr->src;
     npcb->state = SYN_RCVD;
     npcb->state = SYN_RCVD;

+ 7 - 1
lwip/src/include/lwip/netif.h

@@ -93,6 +93,9 @@ extern "C" {
 /** If set, the netif has IGMP capability.
 /** If set, the netif has IGMP capability.
  * Set by the netif driver in its init function. */
  * Set by the netif driver in its init function. */
 #define NETIF_FLAG_IGMP         0x80U
 #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
 /** Function prototype for netif init functions. Set up flags and output/linkoutput
  * callback functions in this function.
  * callback functions in this function.
@@ -185,7 +188,7 @@ struct netif {
   /** link level hardware address of this interface */
   /** link level hardware address of this interface */
   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
   /** flags (see NETIF_FLAG_ above) */
   /** flags (see NETIF_FLAG_ above) */
-  u8_t flags;
+  u16_t flags;
   /** descriptive abbreviation */
   /** descriptive abbreviation */
   char name[2];
   char name[2];
   /** number of this interface */
   /** number of this interface */
@@ -266,11 +269,14 @@ void netif_remove(struct netif * netif);
    structure. */
    structure. */
 struct netif *netif_find(char *name);
 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_default(struct netif *netif);
 
 
 void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr);
 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_netmask(struct netif *netif, ip_addr_t *netmask);
 void netif_set_gw(struct netif *netif, ip_addr_t *gw);
 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_up(struct netif *netif);
 void netif_set_down(struct netif *netif);
 void netif_set_down(struct netif *netif);

+ 4 - 1
lwip/src/include/lwip/tcp.h

@@ -162,7 +162,9 @@ enum tcp_state {
   /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
   /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
   DEF_ACCEPT_CALLBACK \
   DEF_ACCEPT_CALLBACK \
   /* ports are in host byte order */ \
   /* 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 */
 /* the TCP protocol control block */
@@ -339,6 +341,7 @@ void             tcp_err     (struct tcp_pcb *pcb, tcp_err_fn err);
 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
 err_t            tcp_bind    (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
 err_t            tcp_bind    (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
                               u16_t port);
                               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,
 err_t            tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
                               u16_t port, tcp_connected_fn connected);
                               u16_t port, tcp_connected_fn connected);