]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/commitdiff
Merged from DEVEL into main tree.
authorlikewise <likewise>
Fri, 14 Nov 2003 13:17:23 +0000 (13:17 +0000)
committerlikewise <likewise>
Fri, 14 Nov 2003 13:17:23 +0000 (13:17 +0000)
45 files changed:
CHANGELOG
doc/savannah.txt
src/api/api_lib.c
src/api/api_msg.c
src/api/err.c
src/api/sockets.c
src/api/tcpip.c
src/core/inet.c
src/core/inet6.c
src/core/ipv4/icmp.c
src/core/ipv4/ip.c
src/core/ipv4/ip_frag.c
src/core/ipv6/icmp6.c
src/core/ipv6/ip6.c
src/core/ipv6/ip6_addr.c
src/core/mem.c
src/core/memp.c
src/core/netif.c
src/core/pbuf.c
src/core/raw.c [new file with mode: 0644]
src/core/stats.c
src/core/sys.c
src/core/tcp.c
src/core/tcp_in.c
src/core/tcp_out.c
src/core/udp.c
src/include/ipv4/lwip/ip.h
src/include/lwip/api.h
src/include/lwip/debug.h
src/include/lwip/mem.h
src/include/lwip/memp.h
src/include/lwip/opt.h
src/include/lwip/pbuf.h
src/include/lwip/raw.h [new file with mode: 0644]
src/include/lwip/sockets.h
src/include/lwip/stats.h
src/include/lwip/tcp.h
src/include/lwip/udp.h
src/netif/etharp.c
src/netif/ethernetif.c
src/netif/loopif.c
src/netif/ppp/auth.c
src/netif/ppp/ppp.c
src/netif/ppp/ppp.h
src/netif/slipif.c

index 7532beed1ffebbf08e310fd389dba199c6ab07ce..1cc2baf150b054333d86113a4b61938210d10a6e 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,17 +1,30 @@
 HISTORY
 
+(todo)
+
+  * Fix unaligned 16-bit access in checksum routine.
+
 (current)
 
   ++ Bug fixes:
 
-  * some debug formatters and casts fixed.
-  * numerous fixes in PPP.
+  * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
+  * Packets sent from ARP queue had invalid source hardware address.
+  * Some debug formatters and casts fixed.
+  * Numerous fixes in PPP.
 
   ++ Changes:
 
   * DEBUGF now is LWIP_DEBUGF
   * pbuf_dechain() has been re-enabled.
-  * Mentioned the changed use of CVS branches in README.
+  * Mentioned the use of CVS branches in README.
+  * Pass-by ARP requests do now update the cache.
+
+  ++ New features:
+
+  * No longer dependent on ctype.h.
+  * New socket options.
+  * Raw IP pcb support.
 
 (STABLE-0_6_3)
 
index f537eb05b8bb72923ce72c7cc85de7d8a3a3804a..92f90873e7d6bf556745153920ec655e1a6bed83 100644 (file)
@@ -11,7 +11,7 @@ Table of Contents:
 1 Anonymous CVS checkouts and updates
 -------------------------------------
 
-Obtain lwIP from the STABLE tree (on the CVS main trunk)
+Obtain lwIP from the CVS main trunk (stable)
 
 cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
 cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
@@ -24,29 +24,37 @@ cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_
 Or, obtain a development branch as follows:
 
 cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
-cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-devel lwip
+cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
 
 
-3 Merging from DEVEL branch to main trunk (stable branch)
+3 Merging from DEVEL branch to main trunk (stable)
 ---------------------------------------------------------
 
-Merging from DEVEL to main requires that the DEVEL branch
-has a tag indicating the previous merger. This tag is
-called 'merged_from_DEVEL_to_main'.
+Merging is a delicate process in CVS and requires the
+following disciplined steps in order to prevent conflicts
+in the future. Conflicts can be hard to solve!
+
+Merging from branch A to branch B requires that the A branch
+has a tag indicating the previous merger. This tag is called
+'merged_from_A_to_B'. After merging, the tag is moved in the
+A branch to remember this merger for future merge actions.
 
 IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
-REPOSITORY, THE TAG MUST BE SET ON THE SOURCE OF THE
-MERGE BRANCH (REPLACING EXISTING TAGS WITH THE SAME NAME).
+REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
+MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
 
 Merge all changes in DEVEL since our last merge to main:
 
 In the working copy of the main trunk:
 cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL 
 
-Now move the tag in the DEVEL branch to this merge point,
-so we can use this for future merges.
+(This will apply the changes between 'merged_from_DEVEL_to_main'
+and 'DEVEL' to your work set of files)
+
+If this worked out OK, we now move the tag in the DEVEL branch
+to this merge point, so we can use this point for future merges:
 
-cvs -z4 rtag -F -r DEVEL merged_from_DEVEL_to_main lwip 
+cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip 
 
 4 How to release lwIP
 ---------------------
@@ -61,7 +69,7 @@ is not created locally.
 cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
 cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
 
-Archive this directory using tar.
+Archive this directory using tar, gzip'd, bzip2'd and zip'd.
 
 tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
 
@@ -74,17 +82,15 @@ Now, make a new release by creating a new directory for it (these are
 Savannah conventions so that it shows up in the Files list real nice):
 
 mkdir stable.pkg
-cd stable.pkg
-mkdir 0.6.3
-cd 0.6.3
+mkdir stable.pkg 0.6.3
 
 We can now copy the tar archive we made earlier into the release directory:
 
-cp /../../../lwip-0.6.3.tar.gz .
+cp ../../../lwip-0.6.3.tar.gz .
 
 Finally, synchronize this directory upwards to Savannah:
 
-rsync -n -e "ssh -1" -t -u -v -r . likewise@savannah.nongnu.org:/upload/lwip
+rsync -n -e "ssh -1" -t -u -v -r *.pkg likewise@savannah.nongnu.org:/upload/lwip
 
 This does a "dry run": no files are modified! After you have confirmed that
 this is what you intended to do, remove "-n" and actually synchronize for
index 80b2d08883a07fbcc429b95576bfdb3dfe17c831..8c51909032a07a5ee3b0feb57a5a3eb6d2b4b5dd 100644 (file)
@@ -38,7 +38,7 @@
 #include "lwip/api_msg.h"
 #include "lwip/memp.h"
 
-/*-----------------------------------------------------------------------------------*/
+
 struct
 netbuf *netbuf_new(void)
 {
@@ -53,7 +53,7 @@ netbuf *netbuf_new(void)
     return NULL;
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_delete(struct netbuf *buf)
 {
@@ -65,7 +65,7 @@ netbuf_delete(struct netbuf *buf)
     memp_free(MEMP_NETBUF, buf);
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void *
 netbuf_alloc(struct netbuf *buf, u16_t size)
 {
@@ -80,7 +80,7 @@ netbuf_alloc(struct netbuf *buf, u16_t size)
   buf->ptr = buf->p;
   return buf->p->payload;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_free(struct netbuf *buf)
 {
@@ -89,7 +89,7 @@ netbuf_free(struct netbuf *buf)
   }
   buf->p = buf->ptr = NULL;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
 {
@@ -101,7 +101,7 @@ netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
   buf->p->len = buf->p->tot_len = size;
   buf->ptr = buf->p;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_chain(struct netbuf *head, struct netbuf *tail)
 {
@@ -109,13 +109,13 @@ netbuf_chain(struct netbuf *head, struct netbuf *tail)
   head->ptr = head->p;
   memp_free(MEMP_NETBUF, tail);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 netbuf_len(struct netbuf *buf)
 {
   return buf->p->tot_len;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
 {
@@ -126,7 +126,7 @@ netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
   *len = buf->ptr->len;
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 s8_t
 netbuf_next(struct netbuf *buf)
 {
@@ -139,13 +139,13 @@ netbuf_next(struct netbuf *buf)
   }
   return 0;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_first(struct netbuf *buf)
 {
   buf->ptr = buf->p;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
 {
@@ -154,7 +154,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
 
   left = 0;
 
-  if (buf == NULL) {
+  if(buf == NULL || dataptr == NULL) {
     return;
   }
   
@@ -174,34 +174,38 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
 {
   netbuf_copy_partial(buf, dataptr, len, 0);
 }
-/*-----------------------------------------------------------------------------------*/
+
 struct ip_addr *
 netbuf_fromaddr(struct netbuf *buf)
 {
   return buf->fromaddr;
 }
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 netbuf_fromport(struct netbuf *buf)
 {
   return buf->fromport;
 }
-/*-----------------------------------------------------------------------------------*/
+
 struct
-netconn *netconn_new(enum netconn_type t)
+netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
+                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
 {
   struct netconn *conn;
+  struct api_msg *msg;
 
   conn = memp_malloc(MEMP_NETCONN);
   if (conn == NULL) {
     return NULL;
   }
+  
+  conn->err = ERR_OK;
   conn->type = t;
   conn->pcb.tcp = NULL;
 
@@ -214,25 +218,44 @@ netconn *netconn_new(enum netconn_type t)
   conn->sem = SYS_SEM_NULL;
   conn->state = NETCONN_NONE;
   conn->socket = 0;
-  conn->callback = 0;
+  conn->callback = callback;
   conn->recv_avail = 0;
+
+  if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
+    memp_free(MEMP_NETCONN, conn);
+    return NULL;
+  }
+  
+  msg->type = API_MSG_NEWCONN;
+  msg->msg.msg.bc.port = proto; /* misusing the port field */
+  msg->msg.conn = conn;
+  api_msg_post(msg);  
+  sys_mbox_fetch(conn->mbox, NULL);
+  memp_free(MEMP_API_MSG, msg);
+
+  if ( conn->err != ERR_OK ) {
+    memp_free(MEMP_NETCONN, conn);
+    return NULL;
+  }
+
   return conn;
 }
-/*-----------------------------------------------------------------------------------*/
+
+
+struct
+netconn *netconn_new(enum netconn_type t)
+{
+  return netconn_new_with_proto_and_callback(t,0,NULL);
+}
+
 struct
 netconn *netconn_new_with_callback(enum netconn_type t,
                                    void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
 {
-    struct netconn *conn;
-    
-    /* get a netconn and then initialize callback pointer and socket */
-    conn = netconn_new(t);
-    if (conn)
-        conn->callback = callback;
-    return conn;
+  return netconn_new_with_proto_and_callback(t,0,callback);
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_delete(struct netconn *conn)
 {
@@ -286,18 +309,21 @@ netconn_delete(struct netconn *conn)
   memp_free(MEMP_NETCONN, conn);
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 enum netconn_type
 netconn_type(struct netconn *conn)
 {
   return conn->type;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_peer(struct netconn *conn, struct ip_addr *addr,
        u16_t *port)
 {
   switch (conn->type) {
+  case NETCONN_RAW:
+    /* return an error as connecting is only a helper for upper layers */
+    return ERR_CONN;
   case NETCONN_UDPLITE:
   case NETCONN_UDPNOCHKSUM:
   case NETCONN_UDP:
@@ -316,12 +342,16 @@ netconn_peer(struct netconn *conn, struct ip_addr *addr,
   }
   return (conn->err = ERR_OK);
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_addr(struct netconn *conn, struct ip_addr **addr,
        u16_t *port)
 {
   switch (conn->type) {
+  case NETCONN_RAW:
+    *addr = &(conn->pcb.raw->local_ip);
+    *port = conn->pcb.raw->protocol;
+    break;
   case NETCONN_UDPLITE:
   case NETCONN_UDPNOCHKSUM:
   case NETCONN_UDP:
@@ -335,7 +365,7 @@ netconn_addr(struct netconn *conn, struct ip_addr **addr,
   }
   return (conn->err = ERR_OK);
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_bind(struct netconn *conn, struct ip_addr *addr,
       u16_t port)
@@ -366,7 +396,7 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr,
   return conn->err;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_connect(struct netconn *conn, struct ip_addr *addr,
        u16_t port)
@@ -417,7 +447,7 @@ netconn_disconnect(struct netconn *conn)
   return conn->err;
 
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_listen(struct netconn *conn)
 {
@@ -444,7 +474,7 @@ netconn_listen(struct netconn *conn)
   memp_free(MEMP_API_MSG, msg);
   return conn->err;
 }
-/*-----------------------------------------------------------------------------------*/
+
 struct netconn *
 netconn_accept(struct netconn *conn)
 {
@@ -461,7 +491,7 @@ netconn_accept(struct netconn *conn)
   
   return newconn;
 }
-/*-----------------------------------------------------------------------------------*/
+
 struct netbuf *
 netconn_recv(struct netconn *conn)
 {
@@ -557,7 +587,7 @@ netconn_recv(struct netconn *conn)
 
   return buf;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_send(struct netconn *conn, struct netbuf *buf)
 {
@@ -585,7 +615,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
   memp_free(MEMP_API_MSG, msg);
   return conn->err;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
 {
@@ -661,7 +691,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
   
   return conn->err;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_close(struct netconn *conn)
 {
@@ -689,10 +719,10 @@ netconn_close(struct netconn *conn)
   memp_free(MEMP_API_MSG, msg);
   return conn->err;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 netconn_err(struct netconn *conn)
 {
   return conn->err;
 }
-/*-----------------------------------------------------------------------------------*/
+
index de03dca929017f5dfdfa62fe5a225318f33d4938..3fb2dbbbb40af346306d98ebdcf08076f749b181 100644 (file)
 #include "lwip/sys.h"
 #include "lwip/tcpip.h"
 
+#if LWIP_RAW
+static int
+recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+    struct ip_addr *addr)
+{
+  struct netbuf *buf;
+  struct netconn *conn;
+
+  conn = arg;
+  if (!conn) return 0;
+
+  if (conn->recvmbox != SYS_MBOX_NULL) {
+    if (!(buf = memp_malloc(MEMP_NETBUF))) {
+      return 0;
+    }
+    pbuf_ref(p);
+    buf->p = p;
+    buf->ptr = p;
+    buf->fromaddr = addr;
+    buf->fromport = pcb->protocol;
+
+    conn->recv_avail += p->tot_len;
+    /* Register event with callback */
+    if (conn->callback)
+        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
+    sys_mbox_post(conn->recvmbox, buf);
+  }
+
+  return 0; /* do not eat the packet */
+}
+#endif
 #if LWIP_UDP
 static void
 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@@ -72,7 +103,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
 }
 #endif /* LWIP_UDP */
 #if LWIP_TCP
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
 {
@@ -103,7 +134,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
   return ERR_OK;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 poll_tcp(void *arg, struct tcp_pcb *pcb)
 {
@@ -117,7 +148,7 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
   }
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
 {
@@ -134,7 +165,7 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
   
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 err_tcp(void *arg, err_t err)
 {
@@ -165,7 +196,7 @@ err_tcp(void *arg, err_t err)
     sys_sem_signal(conn->sem);
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 setup_tcp(struct netconn *conn)
 {
@@ -178,7 +209,7 @@ setup_tcp(struct netconn *conn)
   tcp_poll(pcb, poll_tcp, 4);
   tcp_err(pcb, err_tcp);
 }
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
 {
@@ -234,17 +265,83 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
   return ERR_OK;
 }
 #endif /* LWIP_TCP */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_newconn(struct api_msg_msg *msg)
 {
+   if(msg->conn->pcb.tcp != NULL) {
+   /* This "new" connection already has a PCB allocated. */
+   /* Is this an error condition? Should it be deleted? 
+      We currently just are happy and return. */
+     sys_mbox_post(msg->conn->mbox, NULL);
+     return;
+   }
+
+   msg->conn->err = ERR_OK;
+
+   /* Allocate a PCB for this connection */
+   switch(msg->conn->type) {
+#if LWIP_RAW
+   case NETCONN_RAW:
+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
+     break;
+#endif
+#if LWIP_UDP
+   case NETCONN_UDPLITE:
+      msg->conn->pcb.udp = udp_new();
+      if(msg->conn->pcb.udp == NULL) {
+         msg->conn->err = ERR_MEM;
+         break;
+      }
+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+      break;
+   case NETCONN_UDPNOCHKSUM:
+      msg->conn->pcb.udp = udp_new();
+      if(msg->conn->pcb.udp == NULL) {
+         msg->conn->err = ERR_MEM;
+         break;
+      }
+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+      break;
+   case NETCONN_UDP:
+      msg->conn->pcb.udp = udp_new();
+      if(msg->conn->pcb.udp == NULL) {
+         msg->conn->err = ERR_MEM;
+         break;
+      }
+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+      break;
+#endif /* LWIP_UDP */
+#if LWIP_TCP
+   case NETCONN_TCP:
+      msg->conn->pcb.tcp = tcp_new();
+      if(msg->conn->pcb.tcp == NULL) {
+         msg->conn->err = ERR_MEM;
+         break;
+      }
+      setup_tcp(msg->conn);
+      break;
+#endif
+   }
+   
+  
+  sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
+
 static void
 do_delconn(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      raw_remove(msg->conn->pcb.raw);
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -287,12 +384,18 @@ do_delconn(struct api_msg_msg *msg)
     sys_mbox_post(msg->conn->mbox, NULL);
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_bind(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp == NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       msg->conn->pcb.udp = udp_new();
@@ -319,6 +422,11 @@ do_bind(struct api_msg_msg *msg)
     }
   }
   switch (msg->conn->type) {
+#if LWIP_RAW
+  case NETCONN_RAW:
+    msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
+    break;
+#endif
 #if LWIP_UDP
   case NETCONN_UDPLITE:
     /* FALLTHROUGH */
@@ -339,7 +447,7 @@ do_bind(struct api_msg_msg *msg)
   sys_mbox_post(msg->conn->mbox, NULL);
 }
 #if LWIP_TCP
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
 {
@@ -359,12 +467,18 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
   return ERR_OK;
 }
 #endif  
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_connect(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp == NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       msg->conn->pcb.udp = udp_new();
@@ -410,6 +524,12 @@ do_connect(struct api_msg_msg *msg)
     }
   }
   switch (msg->conn->type) {
+#if LWIP_RAW
+  case NETCONN_RAW:
+    raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
+    sys_mbox_post(msg->conn->mbox, NULL);
+    break;
+#endif
 #if LWIP_UDP
   case NETCONN_UDPLITE:
     /* FALLTHROUGH */
@@ -428,6 +548,7 @@ do_connect(struct api_msg_msg *msg)
     do_connected);
     /*tcp_output(msg->conn->pcb.tcp);*/
 #endif
+
   default:
     break;
   }
@@ -438,6 +559,11 @@ do_disconnect(struct api_msg_msg *msg)
 {
 
   switch (msg->conn->type) {
+#if LWIP_RAW
+  case NETCONN_RAW:
+    /* Do nothing as connecting is only a helper for upper lwip layers */
+    break;
+#endif
 #if LWIP_UDP
   case NETCONN_UDPLITE:
     /* FALLTHROUGH */
@@ -453,12 +579,17 @@ do_disconnect(struct api_msg_msg *msg)
   sys_mbox_post(msg->conn->mbox, NULL);
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_listen(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -491,12 +622,17 @@ do_listen(struct api_msg_msg *msg)
   }
   sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_accept(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -511,12 +647,17 @@ do_accept(struct api_msg_msg *msg)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_send(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      raw_send(msg->conn->pcb.raw, msg->msg.p);
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -532,7 +673,7 @@ do_send(struct api_msg_msg *msg)
   }
   sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_recv(struct api_msg_msg *msg)
 {
@@ -545,7 +686,7 @@ do_recv(struct api_msg_msg *msg)
 #endif  
   sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_write(struct api_msg_msg *msg)
 {
@@ -554,6 +695,11 @@ do_write(struct api_msg_msg *msg)
 #endif  
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      msg->conn->err = ERR_VAL;
+      break;
+#endif
 #if LWIP_UDP 
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -571,7 +717,7 @@ do_write(struct api_msg_msg *msg)
    segments when new outgoing data arrives from the user if any
    previously transmitted data on the connection remains
    unacknowledged. */
-      if (err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) {
+      if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
   tcp_output(msg->conn->pcb.tcp);
       }
       msg->conn->err = err;
@@ -588,7 +734,7 @@ do_write(struct api_msg_msg *msg)
   }
   sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 do_close(struct api_msg_msg *msg)
 {
@@ -598,6 +744,10 @@ do_close(struct api_msg_msg *msg)
 
   if (msg->conn->pcb.tcp != NULL) {
     switch (msg->conn->type) {
+#if LWIP_RAW
+    case NETCONN_RAW:
+      break;
+#endif
 #if LWIP_UDP
     case NETCONN_UDPLITE:
       /* FALLTHROUGH */
@@ -619,7 +769,7 @@ do_close(struct api_msg_msg *msg)
   }
   sys_mbox_post(msg->conn->mbox, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 typedef void (* api_msg_decode)(struct api_msg_msg *msg);
 static api_msg_decode decode[API_MSG_MAX] = {
   do_newconn,
@@ -639,12 +789,12 @@ api_msg_input(struct api_msg *msg)
 {  
   decode[msg->type](&(msg->msg));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 api_msg_post(struct api_msg *msg)
 {
   tcpip_apimsg(msg);
 }
-/*-----------------------------------------------------------------------------------*/
+
 
 
index 7dc6e33fda6f6decb5a471c3084c15e8023dad17..ea8b75a0c49f4abf70cc5e28aa2b071804210d0c 100644 (file)
@@ -47,13 +47,13 @@ static char *err_strerr[] = {"Ok.",
            "Address in use."
 };
 
-/*-----------------------------------------------------------------------------------*/
+
 char *
 lwip_strerr(err_t err)
 {
   return err_strerr[-err];
 
 }
-/*-----------------------------------------------------------------------------------*/
+
 
 #endif /* LWIP_DEBUG */
index e93c5bc50f3b2abe9780c93fdf96d386a6621f17..c39cf921172b0953332d8c4c14e3880f1fbad786 100644 (file)
@@ -99,7 +99,7 @@ static int err_to_errno_table[11] = {
       set_errno(sk->err); \
 } while (0)
 
-/*-----------------------------------------------------------------------------------*/
+
 static struct lwip_socket *
 get_socket(int s)
 {
@@ -121,7 +121,7 @@ get_socket(int s)
 
   return sock;
 }
-/*-----------------------------------------------------------------------------------*/
+
 static int
 alloc_socket(struct netconn *newconn)
 {
@@ -150,7 +150,7 @@ alloc_socket(struct netconn *newconn)
   sys_sem_signal(socksem);
   return -1;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
 {
@@ -164,6 +164,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -197,16 +198,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
   newconn->socket = newsock;
   sys_sem_signal(socksem);
 
-#if SOCKETS_DEBUG
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
   ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
-#endif
 
   sock_set_errno(sock, 0);
   return newsock;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
 {
@@ -217,17 +216,16 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
   local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
   local_port = ((struct sockaddr_in *)name)->sin_port;
 
-#if SOCKETS_DEBUG
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
   ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
-#endif
 
   err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
 
@@ -241,7 +239,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
   sock_set_errno(sock, 0);
   return 0;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_close(int s)
 {
@@ -257,6 +255,7 @@ lwip_close(int s)
   sock = get_socket(s);
   if (!sock) {
       sys_sem_signal(socksem);
+      set_errno(EBADF);
       return -1;
   }
 
@@ -271,7 +270,7 @@ lwip_close(int s)
   sock_set_errno(sock, 0);
   return 0;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
 {
@@ -280,6 +279,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -293,11 +293,9 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
     remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
     remote_port = ((struct sockaddr_in *)name)->sin_port;
 
-#if SOCKETS_DEBUG
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
     ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
     LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
-#endif
 
     err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
    }
@@ -312,7 +310,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
   sock_set_errno(sock, 0);
   return 0;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_listen(int s, int backlog)
 {
@@ -322,6 +320,7 @@ lwip_listen(int s, int backlog)
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -336,7 +335,7 @@ lwip_listen(int s, int backlog)
   sock_set_errno(sock, 0);
   return 0;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
         struct sockaddr *from, socklen_t *fromlen)
@@ -351,6 +350,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -411,11 +411,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
 
     memcpy(from, &sin, *fromlen);
 
-#if SOCKETS_DEBUG
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
     ip_addr_debug_print(SOCKETS_DEBUG, addr);
     LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
-#endif
   } else {
 #if SOCKETS_DEBUG > 0
     addr = netbuf_fromaddr(buf);
@@ -444,19 +442,19 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
   sock_set_errno(sock, 0);
   return copylen;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_read(int s, void *mem, int len)
 {
   return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_recv(int s, void *mem, int len, unsigned int flags)
 {
   return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_send(int s, void *data, int size, unsigned int flags)
 {
@@ -468,11 +466,15 @@ lwip_send(int s, void *data, int size, unsigned int flags)
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
   switch (netconn_type(sock->conn)) {
+  case NETCONN_RAW:
   case NETCONN_UDP:
+  case NETCONN_UDPLITE:
+  case NETCONN_UDPNOCHKSUM:
     /* create a buffer */
     buf = netbuf_new();
 
@@ -509,7 +511,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
   sock_set_errno(sock, 0);
   return size;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_sendto(int s, void *data, int size, unsigned int flags,
        struct sockaddr *to, socklen_t tolen)
@@ -521,6 +523,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -530,11 +533,9 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
   remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
   remote_port = ((struct sockaddr_in *)to)->sin_port;
 
-#if SOCKETS_DEBUG
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
   ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
-#endif
 
   netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
 
@@ -548,7 +549,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
   netconn_disconnect(sock->conn);
   return ret;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_socket(int domain, int type, int protocol)
 {
@@ -557,6 +558,10 @@ lwip_socket(int domain, int type, int protocol)
 
   /* create a netconn */
   switch (type) {
+  case SOCK_RAW:
+    conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
+    break;
   case SOCK_DGRAM:
     conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
@@ -589,14 +594,14 @@ lwip_socket(int domain, int type, int protocol)
   set_errno(0);
   return i;
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_write(int s, void *data, int size)
 {
    return lwip_send(s, data, size, 0);
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 static int
 lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
 {
@@ -643,7 +648,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
 }
 
 
-/*-----------------------------------------------------------------------------------*/
+
 int
 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
                struct timeval *timeout)
@@ -723,7 +728,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
             /* Wait forever */
             msectimeout = 0;
         else
-            msectimeout =  ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
+            msectimeout =  ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
 
         i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
 
@@ -789,7 +794,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
     return nready;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
 {
@@ -878,7 +883,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
 
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 
 
 int lwip_shutdown(int s, int how)
@@ -895,6 +900,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -905,11 +911,9 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
   /* get the IP address and port of the remote host */
   netconn_peer(sock->conn, &naddr, &sin.sin_port);
 
-#if SOCKETS_DEBUG
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
   ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
-#endif
 
   sin.sin_port = htons(sin.sin_port);
   sin.sin_addr.s_addr = naddr.addr;
@@ -930,6 +934,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
 
   sock = get_socket(s);
   if (!sock) {
+    set_errno(EBADF);
     return -1;
   }
 
@@ -940,11 +945,9 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
   /* get the IP address and port of the remote host */
   netconn_addr(sock->conn, &naddr, &sin.sin_port);
 
-#if SOCKETS_DEBUG
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
   ip_addr_debug_print(SOCKETS_DEBUG, naddr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
-#endif
 
   sin.sin_port = htons(sin.sin_port);
   sin.sin_addr.s_addr = naddr->addr;
@@ -959,32 +962,190 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
 
 int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
 {
-  int err = ENOSYS;
+  int err = 0;
   struct lwip_socket *sock = get_socket(s);
 
-  if (!sock) {
+  if(!sock) {
+       set_errno(EBADF);
+    return -1;
+  }
+
+  if( NULL == optval || NULL == optlen ) {
+    sock_set_errno( sock, EFAULT );
     return -1;
   }
 
-  if (level == SOL_SOCKET) {
-    switch (optname) {
+  /* Do length and type checks for the various options first, to keep it readable. */
+  switch( level ) {
+   
+/* Level: SOL_SOCKET */
+  case SOL_SOCKET:
+      switch(optname) {
+         
+      case SO_ACCEPTCONN:
+      case SO_BROADCAST:
+      /* UNIMPL case SO_DEBUG: */
+      /* UNIMPL case SO_DONTROUTE: */
       case SO_ERROR:
-        if (!optval || !optlen || (*optlen != sizeof(int))) {
+      case SO_KEEPALIVE:
+      /* UNIMPL case SO_OOBINLINE: */
+      /* UNIMPL case SO_RCVBUF: */
+      /* UNIMPL case SO_SNDBUF: */
+      /* UNIMPL case SO_RCVLOWAT: */
+      /* UNIMPL case SO_SNDLOWAT: */
+#ifdef SO_REUSE
+      case SO_REUSEADDR:
+      case SO_REUSEPORT:
+#endif /* SO_REUSE */
+      case SO_TYPE:
+      /* UNIMPL case SO_USELOOPBACK: */
+        if( *optlen < sizeof(int) ) {
           err = EINVAL;
+        }
           break;
+
+      default:
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
+        err = ENOPROTOOPT;
+      }  /* switch */
+      break;
+                     
+/* Level: IPPROTO_IP */
+  case IPPROTO_IP:
+      switch(optname) {
+      /* UNIMPL case IP_HDRINCL: */
+      /* UNIMPL case IP_RCVDSTADDR: */
+      /* UNIMPL case IP_RCVIF: */
+      case IP_TTL:
+      case IP_TOS:
+        if( *optlen < sizeof(int) ) {
+          err = EINVAL;
         }
-        *(int *)optval = sock->err;
-        sock->err = 0;
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
-        err = 0;
         break;
+
       default:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
+        err = ENOPROTOOPT;
+      }  /* switch */
+      break;
+         
+/* Level: IPPROTO_TCP */
+  case IPPROTO_TCP:
+      if( *optlen < sizeof(int) ) {
+        err = EINVAL;
         break;
     }
-  } else {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
+      
+      /* If this is no TCP socket, ignore any options. */
+      if ( sock->conn->type != NETCONN_TCP ) return 0;
+
+      switch( optname ) {
+      case TCP_NODELAY:
+      case TCP_KEEPALIVE:
+        break;
+         
+      default:
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
+        err = ENOPROTOOPT;
+      }  /* switch */
+      break;
+
+/* UNDEFINED LEVEL */
+  default:
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
+      err = ENOPROTOOPT;
+  }  /* switch */
+
+   
+  if( 0 != err ) {
+    sock_set_errno(sock, err);
+    return -1;
+  }
+   
+
+
+  /* Now do the actual option processing */
+
+  switch(level) {
+   
+/* Level: SOL_SOCKET */
+  case SOL_SOCKET:
+    switch( optname ) {
+
+    /* The option flags */
+    case SO_ACCEPTCONN:
+    case SO_BROADCAST:
+    /* UNIMPL case SO_DEBUG: */
+    /* UNIMPL case SO_DONTROUTE: */
+    case SO_KEEPALIVE:
+    /* UNIMPL case SO_OOBINCLUDE: */
+#ifdef SO_REUSE
+    case SO_REUSEADDR:
+    case SO_REUSEPORT:
+#endif /* SO_REUSE */
+    /*case SO_USELOOPBACK: UNIMPL */
+      *(int*)optval = sock->conn->pcb.tcp->so_options & optname;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));
+      break;
+
+    case SO_TYPE:
+      switch (sock->conn->type) {
+      case NETCONN_RAW:
+        *(int*)optval = SOCK_RAW;
+        break;
+      case NETCONN_TCP:
+        *(int*)optval = SOCK_STREAM;
+        break;
+      case NETCONN_UDP:
+      case NETCONN_UDPLITE:
+      case NETCONN_UDPNOCHKSUM:
+        *(int*)optval = SOCK_DGRAM;
+        break;
+      default: /* unrecognized socket type */
+        *(int*)optval = sock->conn->type;
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));
+      }  /* switch */
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
+      break;
+
+    case SO_ERROR:
+      *(int *)optval = sock->err;
+      sock->err = 0;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
+      break;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_IP */
+  case IPPROTO_IP:
+    switch( optname ) {
+    case IP_TTL:
+      *(int*)optval = sock->conn->pcb.tcp->ttl;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));
+      break;
+    case IP_TOS:
+      *(int*)optval = sock->conn->pcb.tcp->tos;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
+      break;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_TCP */
+  case IPPROTO_TCP:
+    switch( optname ) {
+    case TCP_NODELAY:
+      *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
+      break;
+    case TCP_KEEPALIVE:
+      *(int*)optval = sock->conn->pcb.tcp->keepalive;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
+      break;
+    }  /* switch */
+    break;
   }
+
+
   sock_set_errno(sock, err);
   return err ? -1 : 0;
 }
@@ -992,27 +1153,165 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
 int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
 {
   struct lwip_socket *sock = get_socket(s);
-  int err = ENOSYS;
+  int err = 0;
 
-  if (!sock) {
+  if(!sock) {
+       set_errno(EBADF);
     return -1;
   }
 
-  if (level == SOL_SOCKET) {
-    switch (optname) {
-      case SO_REUSEADDR:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
-           /* XXX just pretend we support this for now */
-          err = 0;
+  if( NULL == optval ) {
+    sock_set_errno( sock, EFAULT );
+    return -1;
+  }
+
+
+  /* Do length and type checks for the various options first, to keep it readable. */
+  switch( level ) {
+
+/* Level: SOL_SOCKET */
+  case SOL_SOCKET:
+    switch(optname) {
+
+    case SO_BROADCAST:
+    /* UNIMPL case SO_DEBUG: */
+    /* UNIMPL case SO_DONTROUTE: */
+    case SO_KEEPALIVE:
+    /* UNIMPL case SO_OOBINLINE: */
+    /* UNIMPL case SO_RCVBUF: */
+    /* UNIMPL case SO_SNDBUF: */
+    /* UNIMPL case SO_RCVLOWAT: */
+    /* UNIMPL case SO_SNDLOWAT: */
+#ifdef SO_REUSE
+    case SO_REUSEADDR:
+    case SO_REUSEPORT:
+#endif /* SO_REUSE */
+    /* UNIMPL case SO_USELOOPBACK: */
+      if( optlen < sizeof(int) ) {
+        err = EINVAL;
+      }
+      break;
+    default:
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
+      err = ENOPROTOOPT;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_IP */
+  case IPPROTO_IP:
+    switch(optname) {
+    /* UNIMPL case IP_HDRINCL: */
+    /* UNIMPL case IP_RCVDSTADDR: */
+    /* UNIMPL case IP_RCVIF: */
+    case IP_TTL:
+    case IP_TOS:
+      if( optlen < sizeof(int) ) {
+        err = EINVAL;
+      }
         break;
       default:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
+      err = ENOPROTOOPT;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_TCP */
+  case IPPROTO_TCP:
+    if( optlen < sizeof(int) ) {
+      err = EINVAL;
         break;
     }
-  } else {
+
+    /* If this is no TCP socket, ignore any options. */
+    if ( sock->conn->type != NETCONN_TCP ) return 0;
+
+    switch( optname ) {
+    case TCP_NODELAY:
+    case TCP_KEEPALIVE:
+      break;
+
+    default:
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
+      err = ENOPROTOOPT;
+    }  /* switch */
+    break;
+
+/* UNDEFINED LEVEL */      
+  default:
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
+    err = ENOPROTOOPT;
+  }  /* switch */
+
+
+  if( 0 != err ) {
+    sock_set_errno(sock, err);
+    return -1;
   }
 
+
+
+  /* Now do the actual option processing */
+
+  switch(level) {
+
+/* Level: SOL_SOCKET */
+  case SOL_SOCKET:
+    switch(optname) {
+
+    /* The option flags */
+    case SO_BROADCAST:
+    /* UNIMPL case SO_DEBUG: */
+    /* UNIMPL case SO_DONTROUTE: */
+    case SO_KEEPALIVE:
+    /* UNIMPL case SO_OOBINCLUDE: */
+#ifdef SO_REUSE
+    case SO_REUSEADDR:
+    case SO_REUSEPORT:
+#endif /* SO_REUSE */
+    /* UNIMPL case SO_USELOOPBACK: */
+      if ( *(int*)optval ) {
+        sock->conn->pcb.tcp->so_options |= optname;
+      } else {
+        sock->conn->pcb.tcp->so_options &= ~optname;
+      }
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
+      break;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_IP */
+  case IPPROTO_IP:
+    switch( optname ) {
+    case IP_TTL:
+      sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
+      break;
+    case IP_TOS:
+      sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
+      break;
+    }  /* switch */
+    break;
+
+/* Level: IPPROTO_TCP */
+  case IPPROTO_TCP:
+    switch( optname ) {
+    case TCP_NODELAY:
+      if ( *(int*)optval ) {
+        sock->conn->pcb.tcp->flags |= TF_NODELAY;
+      } else {
+        sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
+      }
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
+      break;
+    case TCP_KEEPALIVE:
+      sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
+      break;
+    }  /* switch */
+    break;
+  }  /* switch */
+
   sock_set_errno(sock, err);
   return err ? -1 : 0;
 }
@@ -1021,7 +1320,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
 {
   struct lwip_socket *sock = get_socket(s);
 
-  if (!sock) {
+  if(!sock) {
+       set_errno(EBADF);
     return -1;
   }
 
@@ -1035,7 +1335,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
     *((u16_t*)argp) = sock->conn->recv_avail;
 
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
-      sock_set_errno(sock, 0);
+    sock_set_errno(sock, 0);
     return 0;
 
   case FIONBIO:
@@ -1044,7 +1344,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
     else
       sock->flags &= ~O_NONBLOCK;
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
-      sock_set_errno(sock, 0);
+    sock_set_errno(sock, 0);
     return 0;
 
   default:
index 32cdcdf520a3970127c28fa2f3bef9668387d353..e27dae0ccaefb70013ed3807fd4bbca3bb9a38b4 100644 (file)
@@ -50,7 +50,7 @@ static sys_mbox_t mbox;
 static int tcpip_tcp_timer_active = 0;
 
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcpip_tcp_timer(void *arg)
 {
@@ -73,7 +73,7 @@ tcp_timer_needed(void)
   }
 }
 #endif /* LWIP_TCP */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcpip_thread(void *arg)
 {
@@ -113,7 +113,7 @@ tcpip_thread(void *arg)
     memp_free(MEMP_TCPIP_MSG, msg);
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcpip_input(struct pbuf *p, struct netif *inp)
 {
@@ -131,7 +131,7 @@ tcpip_input(struct pbuf *p, struct netif *inp)
   sys_mbox_post(mbox, msg);
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcpip_callback(void (*f)(void *ctx), void *ctx)
 {
@@ -148,7 +148,7 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
   sys_mbox_post(mbox, msg);
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcpip_apimsg(struct api_msg *apimsg)
 {
@@ -162,7 +162,7 @@ tcpip_apimsg(struct api_msg *apimsg)
   msg->msg.apimsg = apimsg;
   sys_mbox_post(mbox, msg);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcpip_init(void (* initfunc)(void *), void *arg)
 {
@@ -171,7 +171,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
   mbox = sys_mbox_new();
   sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
 }
-/*-----------------------------------------------------------------------------------*/
+
 
 
 
index 4feab48f6af1ed72f112342f9e115eddc6b72bb3..a02439873422cda5dd28e136d31f6cb2c2006a78 100644 (file)
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* inet.c
  *
  * Functions common to all TCP/IP modules, such as the Internet checksum and the
  * byte order functions.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 #include "lwip/opt.h"
 
@@ -47,7 +47,7 @@
 #include "lwip/inet.h"
 
 
-/*-----------------------------------------------------------------------------------*/
+
 static u16_t
 lwip_chksum(void *dataptr, int len)
 {
@@ -75,12 +75,12 @@ lwip_chksum(void *dataptr, int len)
 
   return (u16_t)acc;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* inet_chksum_pseudo:
  *
  * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
  */
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum_pseudo(struct pbuf *p,
        struct ip_addr *src, struct ip_addr *dest,
@@ -124,13 +124,13 @@ inet_chksum_pseudo(struct pbuf *p,
   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
   return ~(acc & 0xffffUL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* inet_chksum:
  *
  * Calculates the Internet checksum over a portion of memory. Used primarely for IP
  * and ICMP.
  */
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum(void *dataptr, u16_t len)
 {
@@ -142,7 +142,7 @@ inet_chksum(void *dataptr, u16_t len)
   }
   return ~(acc & 0xffff);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum_pbuf(struct pbuf *p)
 {
@@ -169,7 +169,17 @@ inet_chksum_pbuf(struct pbuf *p)
   return ~(acc & 0xffffUL);
 }
 
-/*-----------------------------------------------------------------------------------*/
+/* Here for now until needed in other places in lwIP */
+#ifndef isascii
+#define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
+#define isascii(c)           in_range(c, 0x20, 0x7f)
+#define isdigit(c)           in_range(c, '0', '9')
+#define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
+#define islower(c)           in_range(c, 'a', 'z')
+#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
+#endif         
+               
+
  /*
   * Ascii internet address interpretation routine.
   * The value returned is in network order.
@@ -318,24 +328,24 @@ u8_t *inet_ntoa(u32_t addr)
   return str;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 #ifndef BYTE_ORDER
 #error BYTE_ORDER is not defined
 #endif
 #if BYTE_ORDER == LITTLE_ENDIAN
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 htons(u16_t n)
 {
   return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 ntohs(u16_t n)
 {
   return htons(n);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u32_t
 htonl(u32_t n)
 {
@@ -344,11 +354,11 @@ htonl(u32_t n)
     ((n & 0xff0000) >> 8) |
     ((n & 0xff000000) >> 24);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u32_t
 ntohl(u32_t n)
 {
   return htonl(n);
 }
-/*-----------------------------------------------------------------------------------*/
+
 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
index ff5d3afa6d4e1d22f0097184b1eecffc8e4cc67f..2a1931fe594c226659671d8ce55c92c614cf87eb 100644 (file)
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* inet6.c
  *
  * Functions common to all TCP/IP modules, such as the Internet checksum and the
  * byte order functions.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 #include "lwip/opt.h"
 
@@ -45,7 +45,7 @@
 #include "lwip/inet.h"
 
 
-/*-----------------------------------------------------------------------------------*/
+
 /* chksum:
  *
  * Sums up all 16 bit words in a memory portion. Also includes any odd byte.
@@ -54,7 +54,7 @@
  * For now, this is not optimized. Must be optimized for the particular processor
  * arcitecture on which it is to run. Preferebly coded in assembler.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static u32_t
 chksum(void *dataptr, u16_t len)
 {
@@ -74,12 +74,12 @@ chksum(void *dataptr, u16_t len)
   return acc;
 
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* inet_chksum_pseudo:
  *
  * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
  */
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum_pseudo(struct pbuf *p,
        struct ip_addr *src, struct ip_addr *dest,
@@ -122,13 +122,13 @@ inet_chksum_pseudo(struct pbuf *p,
   }
   return ~(acc & 0xffff);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* inet_chksum:
  *
  * Calculates the Internet checksum over a portion of memory. Used primarely for IP
  * and ICMP.
  */
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum(void *dataptr, u16_t len)
 {
@@ -139,7 +139,7 @@ inet_chksum(void *dataptr, u16_t len)
   sum += (sum >> 16);
   return ~(sum & 0xffff);
 }
-/*-----------------------------------------------------------------------------------*/
+
 u16_t
 inet_chksum_pbuf(struct pbuf *p)
 {
@@ -165,4 +165,4 @@ inet_chksum_pbuf(struct pbuf *p)
   }
   return ~(acc & 0xffff);
 }
-/*-----------------------------------------------------------------------------------*/
+
index d62013ff0118a5c49aadd6e775622235419d59eb..2a91b44c6178bf84ffe632c10bd70bce080bf0a3 100644 (file)
@@ -43,7 +43,7 @@
 #include "lwip/stats.h"
 
 #include "lwip/snmp.h"
-/*-----------------------------------------------------------------------------------*/
+
 void
 icmp_input(struct pbuf *p, struct netif *inp)
 {
@@ -54,9 +54,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
   struct ip_addr tmpaddr;
   u16_t hlen;
 
-#ifdef ICMP_STATS
-  ++lwip_stats.icmp.recv;
-#endif /* ICMP_STATS */
+  ICMP_STATS_INC(icmp.recv);
   snmp_inc_icmpinmsgs();
 
 
@@ -65,9 +63,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
   if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
     pbuf_free(p);
-#ifdef ICMP_STATS
-    ++lwip_stats.icmp.lenerr;
-#endif /* ICMP_STATS */
+    ICMP_STATS_INC(icmp.lenerr);
     snmp_inc_icmpinerrors();
     return;
   }
@@ -79,9 +75,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
     if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
        ip_addr_ismulticast(&iphdr->dest)) {
       LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
-#ifdef ICMP_STATS
-      ++lwip_stats.icmp.err;
-#endif /* ICMP_STATS */
+      ICMP_STATS_INC(icmp.err);
       pbuf_free(p);
       return;
     }
@@ -90,9 +84,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
     if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
       pbuf_free(p);
-#ifdef ICMP_STATS
-      ++lwip_stats.icmp.lenerr;
-#endif /* ICMP_STATS */
+      ICMP_STATS_INC(icmp.lenerr);
       snmp_inc_icmpinerrors();
 
       return;
@@ -101,9 +93,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
     if (inet_chksum_pbuf(p) != 0) {
       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
       pbuf_free(p);
-#ifdef ICMP_STATS
-      ++lwip_stats.icmp.chkerr;
-#endif /* ICMP_STATS */
+      ICMP_STATS_INC(icmp.chkerr);
       snmp_inc_icmpinerrors();
       return;
     }
@@ -117,28 +107,24 @@ icmp_input(struct pbuf *p, struct netif *inp)
     } else {
       iecho->chksum += htons(ICMP_ECHO << 8);
     }
-#ifdef ICMP_STATS
-    ++lwip_stats.icmp.xmit;
-#endif /* ICMP_STATS */
+    ICMP_STATS_INC(icmp.xmit);
     /* increase number of messages attempted to send */
     snmp_inc_icmpoutmsgs();
     /* increase number of echo replies attempted to send */
     snmp_inc_icmpoutechoreps();
 
     pbuf_header(p, hlen);
-    ip_output_if (p, &(iphdr->src), IP_HDRINCL,
-     IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
+    ip_output_if(p, &(iphdr->src), IP_HDRINCL,
+                IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
     break;
   default:
   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
-#ifdef ICMP_STATS
-    ++lwip_stats.icmp.proterr;
-    ++lwip_stats.icmp.drop;
-#endif /* ICMP_STATS */
+    ICMP_STATS_INC(icmp.proterr);
+    ICMP_STATS_INC(icmp.drop);
   }
   pbuf_free(p);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
 {
@@ -160,19 +146,17 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
   /* calculate checksum */
   idur->chksum = 0;
   idur->chksum = inet_chksum(idur, q->len);
-#ifdef ICMP_STATS
-  ++lwip_stats.icmp.xmit;
-#endif /* ICMP_STATS */
+  ICMP_STATS_INC(icmp.xmit);
   /* increase number of messages attempted to send */
   snmp_inc_icmpoutmsgs();
   /* increase number of destination unreachable messages attempted to send */
   snmp_inc_icmpoutdestunreachs();
 
   ip_output(q, NULL, &(iphdr->src),
-      ICMP_TTL, IP_PROTO_ICMP);
+           ICMP_TTL, 0, IP_PROTO_ICMP);
   pbuf_free(q);
 }
-/*-----------------------------------------------------------------------------------*/
+
 #if IP_FORWARD
 void
 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
@@ -184,13 +168,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
 
   iphdr = p->payload;
-#if ICMP_DEBUG
   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
   LWIP_DEBUGF(ICMP_DEBUG, (" to "));
   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
   LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
-#endif /* ICMP_DEBNUG */
 
   tehdr = q->payload;
   ICMPH_TYPE_SET(tehdr, ICMP_TE);
@@ -202,19 +184,17 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
   /* calculate checksum */
   tehdr->chksum = 0;
   tehdr->chksum = inet_chksum(tehdr, q->len);
-#ifdef ICMP_STATS
-  ++lwip_stats.icmp.xmit;
-#endif /* ICMP_STATS */
+  ICMP_STATS_INC(icmp.xmit);
   /* increase number of messages attempted to send */
   snmp_inc_icmpoutmsgs();
   /* increase number of destination unreachable messages attempted to send */
   snmp_inc_icmpouttimeexcds();
   ip_output(q, NULL, &(iphdr->src),
-      ICMP_TTL, IP_PROTO_ICMP);
+           ICMP_TTL, 0, IP_PROTO_ICMP);
   pbuf_free(q);
 }
 
-#endif /* IP_FORWARDING > 0 */
+#endif /* IP_FORWARD */
 
 
 
index dabced1218489a3f8c06a69dc6e6e9a7dabdf605..258625199d23155764e87aedbdd8daa27fe8ab65 100644 (file)
  */
 
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip.c
  *
  * This is the code for the IP layer.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 #include "lwip/opt.h"
 
@@ -49,6 +49,7 @@
 #include "lwip/inet.h"
 #include "lwip/netif.h"
 #include "lwip/icmp.h"
+#include "lwip/raw.h"
 #include "lwip/udp.h"
 #include "lwip/tcp.h"
 
 #  include "lwip/dhcp.h"
 #endif /* LWIP_DHCP */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_init:
  *
  * Initializes the IP layer.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 ip_init(void)
 {
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_lookup:
  *
  * An experimental feature that will be changed in future versions. Do
  * not depend on it yet...
  */
-/*-----------------------------------------------------------------------------------*/
+
 #ifdef LWIP_DEBUG
 u8_t
 ip_lookup(void *header, struct netif *inp)
@@ -106,11 +107,12 @@ ip_lookup(void *header, struct netif *inp)
 #endif /* IP_OPTIONS == 0 */
 
   switch (IPH_PROTO(iphdr)) {
-#if LWIP_UDP > 0
+#if LWIP_UDP
   case IP_PROTO_UDP:
+  case IP_PROTO_UDPLITE:
     return udp_lookup(iphdr, inp);
 #endif /* LWIP_UDP */
-#if LWIP_TCP > 0
+#if LWIP_TCP
   case IP_PROTO_TCP:
     return 1;
 #endif /* LWIP_TCP */
@@ -121,7 +123,7 @@ ip_lookup(void *header, struct netif *inp)
   }
 }
 #endif /* LWIP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_route:
  *
  * Finds the appropriate network interface for a given IP address. It
@@ -129,7 +131,7 @@ ip_lookup(void *header, struct netif *inp)
  * if the masked IP address of the network interface equals the masked
  * IP address given to the function.
  */
-/*-----------------------------------------------------------------------------------*/
+
 struct netif *
 ip_route(struct ip_addr *dest)
 {
@@ -147,14 +149,14 @@ ip_route(struct ip_addr *dest)
   return netif_default;
 }
 #if IP_FORWARD
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_forward:
  *
  * Forwards an IP packet. It finds an appropriate route for the
  * packet, decrements the TTL value of the packet, adjusts the
  * checksum and outputs the packet on the appropriate interface.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
 {
@@ -199,10 +201,8 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
                     iphdr->dest.addr));
 
-#ifdef IP_STATS
-  ++lwip_stats.ip.fw;
-  ++lwip_stats.ip.xmit;
-#endif /* IP_STATS */
+  IP_STATS_INC(ip.fw);
+  IP_STATS_INC(ip.xmit);
     snmp_inc_ipforwdatagrams();
 
   PERF_STOP("ip_forward");
@@ -210,7 +210,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
 }
 #endif /* IP_FORWARD */
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_input:
  *
  * This function is called by the network interface device driver when
@@ -221,30 +221,24 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
  *
  * Finally, the packet is sent to the upper layer protocol input function.
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 ip_input(struct pbuf *p, struct netif *inp) {
   static struct ip_hdr *iphdr;
   static struct netif *netif;
   static u16_t iphdrlen;
 
-#ifdef IP_STATS
-  ++lwip_stats.ip.recv;
-#endif /* IP_STATS */
+  IP_STATS_INC(ip.recv);
   snmp_inc_ipinreceives();
 
   /* identify the IP header */
   iphdr = p->payload;
   if (IPH_V(iphdr) != 4) {
     LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
-#if IP_DEBUG
     ip_debug_print(p);
-#endif /* IP_DEBUG */
     pbuf_free(p);
-#ifdef IP_STATS
-    ++lwip_stats.ip.err;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.err);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipunknownprotos();
     return ERR_OK;
   }
@@ -259,10 +253,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
       iphdrlen, p->len));
     /* free (drop) packet pbufs */
     pbuf_free(p);
-#ifdef IP_STATS
-    ++lwip_stats.ip.lenerr;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.lenerr);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipindiscards();
     return ERR_OK;
   }
@@ -271,14 +263,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
   if (inet_chksum(iphdr, iphdrlen) != 0) {
 
     LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
-#if IP_DEBUG
     ip_debug_print(p);
-#endif /* IP_DEBUG */
     pbuf_free(p);
-#ifdef IP_STATS
-    ++lwip_stats.ip.chkerr;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.chkerr);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipindiscards();
     return ERR_OK;
   }
@@ -363,10 +351,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
     pbuf_free(p);
     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
                   ntohs(IPH_OFFSET(iphdr))));
-#ifdef IP_STATS
-    ++lwip_stats.ip.opterr;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.opterr);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipunknownprotos();
     return ERR_OK;
   }
@@ -376,30 +362,31 @@ ip_input(struct pbuf *p, struct netif *inp) {
   if (iphdrlen > IP_HLEN) {
     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
     pbuf_free(p);
-#ifdef IP_STATS
-    ++lwip_stats.ip.opterr;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.opterr);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipunknownprotos();
     return ERR_OK;
   }
 #endif /* IP_OPTIONS == 0 */
 
   /* send to upper layers */
-#if IP_DEBUG
   LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
   ip_debug_print(p);
   LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
-#endif /* IP_DEBUG */
+
+#if LWIP_RAW
+  if (!raw_input(p, inp)) {
+#endif /* LWIP_RAW */
 
   switch (IPH_PROTO(iphdr)) {
-#if LWIP_UDP > 0
+#if LWIP_UDP
   case IP_PROTO_UDP:
+  case IP_PROTO_UDPLITE:
     snmp_inc_ipindelivers();
     udp_input(p, inp);
     break;
 #endif /* LWIP_UDP */
-#if LWIP_TCP > 0
+#if LWIP_TCP
   case IP_PROTO_TCP:
     snmp_inc_ipindelivers();
     tcp_input(p, inp);
@@ -420,17 +407,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
 
     LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
 
-#ifdef IP_STATS
-    ++lwip_stats.ip.proterr;
-    ++lwip_stats.ip.drop;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.proterr);
+    IP_STATS_INC(ip.drop);
     snmp_inc_ipunknownprotos();
 
   }
+#if LWIP_RAW
+  } /* LWIP_RAW */
+#endif
   return ERR_OK;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_output_if:
  *
  * Sends an IP packet on a network interface. This function constructs
@@ -438,10 +426,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
  * IP address is NULL, the IP address of the outgoing network
  * interface is filled in as source address.
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
-ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
-             u8_t ttl,
+ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+             u8_t ttl, u8_t tos,
              u8_t proto, struct netif *netif)
 {
   static struct ip_hdr *iphdr;
@@ -453,9 +441,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
     if (pbuf_header(p, IP_HLEN)) {
       LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
 
-#ifdef IP_STATS
-      ++lwip_stats.ip.err;
-#endif /* IP_STATS */
+      IP_STATS_INC(ip.err);
       snmp_inc_ipoutdiscards();
       return ERR_BUF;
     }
@@ -467,7 +453,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
 
     ip_addr_set(&(iphdr->dest), dest);
 
-    IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
+    IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
     IPH_LEN_SET(iphdr, htons(p->tot_len));
     IPH_OFFSET_SET(iphdr, htons(IP_DF));
     IPH_ID_SET(iphdr, htons(ip_id));
@@ -492,44 +478,39 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
     return ip_frag(p,netif,dest);
 #endif
 
-#ifdef IP_STATS
-  lwip_stats.ip.xmit++;
-#endif /* IP_STATS */
+  IP_STATS_INC(ip.xmit);
+
   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
-#if IP_DEBUG
   ip_debug_print(p);
-#endif /* IP_DEBUG */
 
   LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
 
   return netif->output(netif, p, dest);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_output:
  *
  * Simple interface to ip_output_if. It finds the outgoing network
  * interface and calls upon ip_output_if to do the actual work.
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
-          u8_t ttl, u8_t proto)
+          u8_t ttl, u8_t tos, u8_t proto)
 {
   struct netif *netif;
 
   if ((netif = ip_route(dest)) == NULL) {
     LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
 
-#ifdef IP_STATS
-    ++lwip_stats.ip.rterr;
-#endif /* IP_STATS */
+    IP_STATS_INC(ip.rterr);
     snmp_inc_ipoutdiscards();
     return ERR_RTE;
   }
 
-  return ip_output_if (p, src, dest, ttl, proto, netif);
+  return ip_output_if(p, src, dest, ttl, tos, proto, netif);
 }
-/*-----------------------------------------------------------------------------------*/
+
 #if IP_DEBUG
 void
 ip_debug_print(struct pbuf *p)
@@ -573,7 +554,7 @@ ip_debug_print(struct pbuf *p)
   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
 }
 #endif /* IP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
 
 
 
index 8f0b72992fc9ad0bb51ee608f11b58eb82cd9e0d..141293ff14c5eae37e0ca48f05efb60573761926 100644 (file)
  * 
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_frag.c
  *
  * This is the code for IP segmentation and reassembly
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 #include "lwip/opt.h"
 #include "lwip/sys.h"
@@ -109,9 +109,7 @@ ip_reass(struct pbuf *p)
   u16_t offset, len;
   u16_t i;
 
-#ifdef IP_STATS
-  ++lwip_stats.ip_frag.recv;
-#endif /* IP_STATS */
+  IPFRAG_STATS_INC(ip_frag.recv);
 
   iphdr = (struct ip_hdr *) ip_reassbuf;
   fraghdr = (struct ip_hdr *) p->payload;
@@ -135,9 +133,7 @@ ip_reass(struct pbuf *p)
       ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
       IPH_ID(iphdr) == IPH_ID(fraghdr)) {
     LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
-#ifdef IP_STATS
-    ++lwip_stats.ip_frag.cachehit;
-#endif /* IP_STATS */
+    IPFRAG_STATS_INC(ip_frag.cachehit);
     /* Find out the offset in the reassembly buffer where we should
        copy the fragment. */
     len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
@@ -255,13 +251,9 @@ ip_reass(struct pbuf *p)
     q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
     i += q->len;
   }
-#ifdef IP_STATS
-  ++lwip_stats.ip_frag.fw;
-#endif /* IP_STATS */
+  IPFRAG_STATS_INC(ip_frag.fw);
       } else {
-#ifdef IP_STATS
-  ++lwip_stats.ip_frag.memerr;
-#endif /* IP_STATS */
+  IPFRAG_STATS_INC(ip_frag.memerr);
       }
       LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
       return p;
@@ -269,9 +261,7 @@ ip_reass(struct pbuf *p)
   }
 
 nullreturn:
-#ifdef IP_STATS
-  ++lwip_stats.ip_frag.drop;
-#endif /* IP_STATS */
+  IPFRAG_STATS_INC(ip_frag.drop);
   pbuf_free(p);
   return NULL;
 }
@@ -347,9 +337,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
     header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
     pbuf_chain(header, rambuf);
     netif->output(netif, header, dest);
-#ifdef IP_STATS
-    ++lwip_stats.ip_frag.xmit;
-#endif /* IP_STATS */
+    IPFRAG_STATS_INC(ip_frag.xmit);
     pbuf_free(header);
 
     left -= cop;
index 87fd8936beb39b7fa9a568aca43d56a2c57fe4e8..832e04177dfc408907c6e2623743d2a32298d03d 100644 (file)
@@ -42,7 +42,7 @@
 
 #include "lwip/stats.h"
 
-/*-----------------------------------------------------------------------------------*/
+
 void
 icmp_input(struct pbuf *p, struct netif *inp)
 {
@@ -113,7 +113,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
 
   pbuf_free(p);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
 {
@@ -143,7 +143,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
       (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
   pbuf_free(q);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
 {
index 9723516b56b2f9b0137335aa20d3dc05a93c121a..00496f60feec1459427241353d4378c90ceb963d 100644 (file)
  */
 
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip.c
  *
  * This is the code for the IP layer for IPv6.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 #include "lwip/opt.h"
 
 #include "lwip/stats.h"
 
 #include "arch/perf.h"
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_init:
  *
  * Initializes the IP layer.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 ip_init(void)
 {
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_route:
  *
  * Finds the appropriate network interface for a given IP address. It searches the
  * list of network interfaces linearly. A match is found if the masked IP address of
  * the network interface equals the masked IP address given to the function.
  */
-/*-----------------------------------------------------------------------------------*/
+
 struct netif *
 ip_route(struct ip_addr *dest)
 {
@@ -84,14 +84,14 @@ ip_route(struct ip_addr *dest)
 
   return netif_default;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_forward:
  *
  * Forwards an IP packet. It finds an appropriate route for the packet, decrements
  * the TTL value of the packet, adjusts the checksum and outputs the packet on the
  * appropriate interface.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
 {
@@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
 
   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_input:
  *
  * This function is called by the network interface device driver when an IP packet is
@@ -152,7 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
  *
  * Finally, the packet is sent to the upper layer protocol input function.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 ip_input(struct pbuf *p, struct netif *inp) {
   struct ip_hdr *iphdr;
@@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
   PERF_STOP("ip_input");
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_output_if:
  *
  * Sends an IP packet on a network interface. This function constructs the IP header
  * and calculates the IP header checksum. If the source IP address is NULL,
  * the IP address of the outgoing network interface is filled in as source address.
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
        u8_t ttl,
@@ -311,13 +311,13 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
   PERF_STOP("ip_output_if");
   return netif->output(netif, p, dest);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* ip_output:
  *
  * Simple interface to ip_output_if. It finds the outgoing network interface and
  * calls upon ip_output_if to do the actual work.
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
     u8_t ttl, u8_t proto)
@@ -333,7 +333,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
 
   return ip_output_if (p, src, dest, ttl, proto, netif);
 }
-/*-----------------------------------------------------------------------------------*/
+
 #if IP_DEBUG
 void
 ip_debug_print(struct pbuf *p)
@@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
 }
 #endif /* IP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
index a105ba789c011d256b7d90c35828bca0b90394c5..1f6700d361e3073fa8a570147fc9296c10f714fe 100644 (file)
@@ -33,7 +33,7 @@
 #include "lwip/ip_addr.h"
 #include "lwip/inet.h"
 
-/*-----------------------------------------------------------------------------------*/
+
 int
 ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
                 struct ip_addr *mask)
@@ -44,7 +44,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
          (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
         
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
 {
@@ -53,7 +53,7 @@ ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
          addr1->addr[2] == addr2->addr[2] &&
          addr1->addr[3] == addr2->addr[3]);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
 {
@@ -63,7 +63,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
   dest->addr[2] = src->addr[2];
   dest->addr[3] = src->addr[3];*/
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 ip_addr_isany(struct ip_addr *addr)
 {
@@ -71,7 +71,7 @@ ip_addr_isany(struct ip_addr *addr)
   return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 /*#if IP_DEBUG*/
 void
 ip_addr_debug_print(struct ip_addr *addr)
@@ -87,4 +87,4 @@ ip_addr_debug_print(struct ip_addr *addr)
          ntohl(addr->addr[3]) & 0xffff);
 }
 /*#endif*/ /* IP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
index 3a8a3f547d1203dd1d1181b2ca90e0fd33237b37..43f48853d0c442a73add2231a1d2e4d9c22ceb79 100644 (file)
@@ -127,7 +127,7 @@ mem_init(void)
 
   lfree = (struct mem *)ram;
 
-#ifdef MEM_STATS
+#if MEM_STATS
   lwip_stats.mem.avail = MEM_SIZE;
 #endif /* MEM_STATS */
 }
@@ -148,7 +148,7 @@ mem_free(void *rmem)
   
   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
-#ifdef MEM_STATS
+#if MEM_STATS
     ++lwip_stats.mem.err;
 #endif /* MEM_STATS */
     sys_sem_signal(mem_sem);
@@ -164,7 +164,7 @@ mem_free(void *rmem)
     lfree = mem;
   }
   
-#ifdef MEM_STATS
+#if MEM_STATS
   lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
   
 #endif /* MEM_STATS */
@@ -183,7 +183,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
   mem_free(rmem);
   return nmem;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void *
 mem_realloc(void *rmem, mem_size_t newsize)
 {
@@ -215,7 +215,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
   ptr = (u8_t *)mem - ram;
 
   size = mem->next - ptr - SIZEOF_STRUCT_MEM;
-#ifdef MEM_STATS
+#if MEM_STATS
   lwip_stats.mem.used -= (size - newsize);
 #endif /* MEM_STATS */
   
@@ -273,7 +273,7 @@ mem_malloc(mem_size_t size)
       
       mem2->used = 0;      
       mem->used = 1;
-#ifdef MEM_STATS
+#if MEM_STATS
       lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
       /*      if (lwip_stats.mem.max < lwip_stats.mem.used) {
         lwip_stats.mem.max = lwip_stats.mem.used;
@@ -299,7 +299,7 @@ mem_malloc(mem_size_t size)
     }    
   }
   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
-#ifdef MEM_STATS
+#if MEM_STATS
   ++lwip_stats.mem.err;
 #endif /* MEM_STATS */  
   sys_sem_signal(mem_sem);
index 26ae7e007afe30ed6959d4bda7e7d8fb399f82ed..7ecff5f8ce93afacce93732ff27cb2bea822e843 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "lwip/pbuf.h"
 #include "lwip/udp.h"
+#include "lwip/raw.h"
 #include "lwip/tcp.h"
 #include "lwip/api.h"
 #include "lwip/api_msg.h"
@@ -54,6 +55,7 @@ static struct memp *memp_tab[MEMP_MAX];
 
 static const u16_t memp_sizes[MEMP_MAX] = {
   sizeof(struct pbuf),
+  sizeof(struct raw_pcb),
   sizeof(struct udp_pcb),
   sizeof(struct tcp_pcb),
   sizeof(struct tcp_pcb_listen),
@@ -67,6 +69,7 @@ static const u16_t memp_sizes[MEMP_MAX] = {
 
 static const u16_t memp_num[MEMP_MAX] = {
   MEMP_NUM_PBUF,
+  MEMP_NUM_RAW_PCB,
   MEMP_NUM_UDP_PCB,
   MEMP_NUM_TCP_PCB,
   MEMP_NUM_TCP_PCB_LISTEN,
@@ -81,6 +84,9 @@ static const u16_t memp_num[MEMP_MAX] = {
 static u8_t memp_memory[(MEMP_NUM_PBUF *
        MEM_ALIGN_SIZE(sizeof(struct pbuf) +
           sizeof(struct memp)) +
+      MEMP_NUM_RAW_PCB *
+       MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
+          sizeof(struct memp)) +
       MEMP_NUM_UDP_PCB *
        MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
           sizeof(struct memp)) +
@@ -109,12 +115,12 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
        MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
           sizeof(struct memp)))];
 
-/*-----------------------------------------------------------------------------------*/
+
 #if !SYS_LIGHTWEIGHT_PROT
 static sys_sem_t mutex;
 #endif
-/*-----------------------------------------------------------------------------------*/
-#ifdef LWIP_DEBUG
+
+#ifndef LWIP_NOASSERT
 static int
 memp_sanity(void)
 {
@@ -135,7 +141,7 @@ memp_sanity(void)
   return 1;
 }
 #endif /* LWIP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
 void
 memp_init(void)
 {
@@ -143,7 +149,7 @@ memp_init(void)
   u16_t i, j;
   u16_t size;
       
-#ifdef MEMP_STATS
+#if MEMP_STATS
   for(i = 0; i < MEMP_MAX; ++i) {
     lwip_stats.memp[i].used = lwip_stats.memp[i].max =
       lwip_stats.memp[i].err = 0;
@@ -176,19 +182,19 @@ memp_init(void)
 
   
 }
-/*-----------------------------------------------------------------------------------*/
+
 void *
 memp_malloc(memp_t type)
 {
   struct memp *memp;
   void *mem;
-#ifdef SYS_LIGHTWEIGHT_PROT
+#if SYS_LIGHTWEIGHT_PROT
   SYS_ARCH_DECL_PROTECT(old_level);
 #endif
  
   LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
 
-#ifdef SYS_LIGHTWEIGHT_PROT
+#if SYS_LIGHTWEIGHT_PROT
   SYS_ARCH_PROTECT(old_level);
 #else /* SYS_LIGHTWEIGHT_PROT */  
   sys_sem_wait(mutex);
@@ -199,13 +205,13 @@ memp_malloc(memp_t type)
   if (memp != NULL) {    
     memp_tab[type] = memp->next;    
     memp->next = NULL;
-#ifdef MEMP_STATS
+#if MEMP_STATS
     ++lwip_stats.memp[type].used;
     if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
       lwip_stats.memp[type].max = lwip_stats.memp[type].used;
     }
 #endif /* MEMP_STATS */
-#ifdef SYS_LIGHTWEIGHT_PROT
+#if SYS_LIGHTWEIGHT_PROT
     SYS_ARCH_UNPROTECT(old_level);
 #else /* SYS_LIGHTWEIGHT_PROT */
     sys_sem_signal(mutex);
@@ -219,7 +225,7 @@ memp_malloc(memp_t type)
     return mem;
   } else {
     LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
-#ifdef MEMP_STATS
+#if MEMP_STATS
     ++lwip_stats.memp[type].err;
 #endif /* MEMP_STATS */
 #if SYS_LIGHTWEIGHT_PROT
@@ -230,12 +236,12 @@ memp_malloc(memp_t type)
     return NULL;
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 memp_free(memp_t type, void *mem)
 {
   struct memp *memp;
-#ifdef SYS_LIGHTWEIGHT_PROT
+#if SYS_LIGHTWEIGHT_PROT
   SYS_ARCH_DECL_PROTECT(old_level);
 #endif /* SYS_LIGHTWEIGHT_PROT */  
 
@@ -244,13 +250,13 @@ memp_free(memp_t type, void *mem)
   }
   memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
 
-#ifdef SYS_LIGHTWEIGHT_PROT
+#if SYS_LIGHTWEIGHT_PROT
     SYS_ARCH_PROTECT(old_level);
 #else /* SYS_LIGHTWEIGHT_PROT */  
   sys_sem_wait(mutex);
 #endif /* SYS_LIGHTWEIGHT_PROT */  
 
-#ifdef MEMP_STATS
+#if MEMP_STATS
   lwip_stats.memp[type].used--; 
 #endif /* MEMP_STATS */
   
@@ -265,4 +271,4 @@ memp_free(memp_t type, void *mem)
   sys_sem_signal(mutex);
 #endif /* SYS_LIGHTWEIGHT_PROT */  
 }
-/*-----------------------------------------------------------------------------------*/
+
index 187b7b8cdfb09f9752508ed6b08c5a7f8b1a805b..eed853eda94a66eb2606e1c8605289797990c810 100644 (file)
@@ -97,7 +97,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
   /* add this netif to the list */
   netif->next = netif_list;
   netif_list = netif;
-#if NETIF_DEBUG
   LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
     netif->name[0], netif->name[1]));
   ip_addr_debug_print(NETIF_DEBUG, ipaddr);
@@ -106,7 +105,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
   LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
   ip_addr_debug_print(NETIF_DEBUG, gw);
   LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
-#endif /* NETIF_DEBUG */
   return netif;
 }
 
@@ -170,7 +168,7 @@ netif_find(char *name)
   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
   return NULL;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
 {
@@ -191,7 +189,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
       if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
         /* this connection must be aborted */
         struct tcp_pcb *next = pcb->next;
-        LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting pcb %p\n", (void *)pcb));
+        LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
         tcp_abort(pcb);
         pcb = next;
       } else {
@@ -202,8 +200,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
       /* PCB bound to current local interface address? */
       if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
         /* The PCB is listening to the old ipaddr and
-         * is set to listen to the new one instead
-         * TODO: how do we know it is _listening_? */
+         * is set to listen to the new one instead */
         ip_addr_set(&(lpcb->local_ip), ipaddr);
       }
     }
@@ -217,7 +214,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
     (unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
     (unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netif_set_gw(struct netif *netif, struct ip_addr *gw)
 {
@@ -229,7 +226,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
            (unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
            (unsigned int)(ntohl(netif->gw.addr) & 0xff)));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
 {
@@ -241,7 +238,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
            (unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
            (unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netif_set_default(struct netif *netif)
 {
@@ -249,10 +246,10 @@ netif_set_default(struct netif *netif)
   LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
            netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 netif_init(void)
 {
   netif_list = netif_default = NULL;
 }
-/*-----------------------------------------------------------------------------------*/
+
index b42bac14024e66bec8f65f89bd8cd8389aab7fc3..405673f269432eb78105dcd0e2befd7159baced7 100644 (file)
@@ -102,7 +102,7 @@ pbuf_init(void)
   pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
   LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
 
-#ifdef PBUF_STATS
+#if PBUF_STATS
   lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
 #endif /* PBUF_STATS */
 
@@ -113,6 +113,7 @@ pbuf_init(void)
     p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
     p->len = p->tot_len = PBUF_POOL_BUFSIZE;
     p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
+    p->flags = PBUF_FLAG_POOL;
     q = p;
     p = p->next;
   }
@@ -143,7 +144,7 @@ pbuf_pool_alloc(void)
   /* Next, check the actual pbuf pool, but if the pool is locked, we
      pretend to be out of buffers and return NULL. */
   if (pbuf_pool_free_lock) {
-#ifdef PBUF_STATS
+#if PBUF_STATS
     ++lwip_stats.pbuf.alloc_locked;
 #endif /* PBUF_STATS */
     return NULL;
@@ -156,7 +157,7 @@ pbuf_pool_alloc(void)
       pbuf_pool = p->next;
     }
 #if !SYS_LIGHTWEIGHT_PROT
-#ifdef PBUF_STATS
+#if PBUF_STATS
   } else {
     ++lwip_stats.pbuf.alloc_locked;
 #endif /* PBUF_STATS */
@@ -164,7 +165,7 @@ pbuf_pool_alloc(void)
   pbuf_pool_alloc_lock = 0;
 #endif /* SYS_LIGHTWEIGHT_PROT */
 
-#ifdef PBUF_STATS
+#if PBUF_STATS
   if (p != NULL) {
     ++lwip_stats.pbuf.used;
     if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
@@ -243,7 +244,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
     p = pbuf_pool_alloc();
     LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
     if (p == NULL) {
-#ifdef PBUF_STATS
+#if PBUF_STATS
       ++lwip_stats.pbuf.err;
 #endif /* PBUF_STATS */
       return NULL;
@@ -258,8 +259,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
     p->tot_len = length;
     /* set the length of the first pbuf in the chain */
     p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
-    /* set pbuf type */
-    p->flags = PBUF_FLAG_POOL;
     /* set reference count (needed here in case we fail) */
     p->ref = 1;
 
@@ -274,7 +273,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
       q = pbuf_pool_alloc();
       if (q == NULL) {
        LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
-#ifdef PBUF_STATS
+#if PBUF_STATS
         ++lwip_stats.pbuf.err;
 #endif /* PBUF_STATS */
         /* free chain so far allocated */
@@ -289,7 +288,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
       q->tot_len = rem_len;
       /* this pbuf length is pool size, unless smaller sized tail */
       q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
-      q->flags = PBUF_FLAG_POOL;
       q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
       LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
               ((u32_t)q->payload % MEM_ALIGNMENT) == 0);
@@ -345,7 +343,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
 }
 
 
-#ifdef PBUF_STATS
+#if PBUF_STATS
 #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
 #else /* PBUF_STATS */
 #define DEC_PBUF_STATS
@@ -412,7 +410,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
   /* first, step over any pbufs that should remain in the chain */
   rem_len = new_len;
   q = p;
-  /* this pbuf should be kept? */
+  /* should this pbuf be kept? */
   while (rem_len > q->len) {
     /* decrease remaining length by pbuf length */
     rem_len -= q->len;
@@ -511,9 +509,9 @@ pbuf_header(struct pbuf *p, s16_t header_size)
  * Decrements the pbuf reference count. If it reaches
  * zero, the pbuf is deallocated.
  *
- * For a pbuf chain, this is repeated for each pbuf in the chain, until
- * a non-zero reference count is encountered, or the end of the chain is
- * reached.
+ * For a pbuf chain, this is repeated for each pbuf in the chain, up to the 
+ * pbuf which has a non-zero reference count after decrementing. 
+ * (This might be the whole chain.)
  *
  * @param pbuf pbuf (chain) to be freed from one user.
  *
@@ -619,7 +617,6 @@ pbuf_clen(struct pbuf *p)
 }
 
 /**
- *
  * Increment the reference count of the pbuf.
  *
  * @param p pbuf to increase reference counter of
@@ -638,20 +635,16 @@ pbuf_ref(struct pbuf *p)
 }
 
 /**
- *
- * Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
- *
- * @param h head pbuf (chain)
- * @param t tail pbuf (chain)
- * @note May not be called on a packet queue.
- *
- * The ->tot_len fields of all pbufs of the head chain are adjusted.
- * The ->next field of the last pbuf of the head chain is adjusted.
- * The ->ref field of the first pbuf of the tail chain is adjusted.
- *
+ * Concatenate two pbufs (each may be a pbuf chain) and take over
+ * the reference of the tail pbuf.
+ * 
+ *  @note The caller MAY NOT reference the tail pbuf afterwards.
+ * 
+ *  @see pbuf_chain()
  */
+
 void
-pbuf_chain(struct pbuf *h, struct pbuf *t)
+pbuf_cat(struct pbuf *h, struct pbuf *t)
 {
   struct pbuf *p;
 
@@ -670,11 +663,31 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
   LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
   /* add total length of second chain to last pbuf total of first chain */
   p->tot_len += t->tot_len;
-  /* chain last pbuf of h chain (p) with first of tail (t) */
+  /* chain last pbuf of head (p) with first of tail (t) */
   p->next = t;
+}
+
+/**
+ * Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
+ * It's the same as pbuf_cat with the addition that it increases the reference count
+ * of the tail.
+ * 
+ * @param h head pbuf (chain)
+ * @param t tail pbuf (chain)
+ * @note May not be called on a packet queue.
+ *
+ * The ->tot_len fields of all pbufs of the head chain are adjusted.
+ * The ->next field of the last pbuf of the head chain is adjusted.
+ * The ->ref field of the first pbuf of the tail chain is adjusted.
+ *
+ */
+void
+pbuf_chain(struct pbuf *h, struct pbuf *t)
+{
+  pbuf_cat(h, t);
   /* t is now referenced to one more time */
   pbuf_ref(t);
-  LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)p, (void *)t));
+  LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
 }
 
 /* For packet queueing. Note that queued packets must be dequeued first
@@ -711,9 +724,9 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
     /* proceed to next packet on queue */
     p = p->next;
   }
-  /* chain last pbuf of h chain (p) with first of tail (t) */
+  /* chain last pbuf of queue with n */
   p->next = n;
-  /* t is now referenced to one more time */
+  /* n is now referenced to one more time */
   pbuf_ref(n);
   LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
 }
@@ -764,7 +777,7 @@ pbuf_dequeue(struct pbuf *p)
  * by pbuf_take()!
  *
  * @note Any replaced pbufs will be freed through pbuf_free().
- * This may allocate them if they become no longer referenced.
+ * This may deallocate them if they become no longer referenced.
  *
  * @param p Head of pbuf chain to process
  *
@@ -889,27 +902,3 @@ pbuf_dechain(struct pbuf *p)
   LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
   return (tail_gone > 0? NULL: q);
 }
-
-/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due
- * to the new way chains are built. */
-#if 0
-/**
- *
- * Increment the reference count of all pbufs in a chain.
- *
- * @param p first pbuf of chain
- *
- */
-void
-pbuf_ref_chain(struct pbuf *p)
-{
-  SYS_ARCH_DECL_PROTECT(old_level);
-  SYS_ARCH_PROTECT(old_level);
-
-  while (p != NULL) {
-    ++p->ref;
-    p = p->next;
-  }
-  SYS_ARCH_UNPROTECT(old_level);
-}
-#endif
diff --git a/src/core/raw.c b/src/core/raw.c
new file mode 100644 (file)
index 0000000..7e3aa41
--- /dev/null
@@ -0,0 +1,310 @@
+/**
+ * @file
+ * Raw Access module
+ *
+ */
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+
+/* raw.c
+ *
+ * The code for the Raw Access to the IP
+ *
+ */
+
+#include "lwip/opt.h"
+
+#include "lwip/def.h"
+#include "lwip/memp.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/ip_addr.h"
+#include "lwip/raw.h"
+
+#include "lwip/stats.h"
+
+#include "arch/perf.h"
+#include "lwip/snmp.h"
+
+#if LWIP_RAW
+/* The list of RAW PCBs */
+
+static struct raw_pcb *raw_pcbs = NULL;
+
+
+void
+raw_init(void)
+{
+  raw_pcbs = NULL;
+}
+
+/**
+ * Determine if in incoming IP packet is covered by a RAW pcb and
+ * and process it if possible
+ *
+ * Given an incoming IP datagram (as a chain of pbufs) this function
+ * finds a corresponding RAW PCB and
+ *
+ * @param pbuf pbuf to be demultiplexed to a RAW PCB.
+ * @param netif network interface on which the datagram was received.
+ * @return 0 if packet is not eated (pbuf needs to be freed then)
+ *         or 1 if the packet has been eaten (pbuf needs not to be freed
+ *         then)
+ *
+ */
+int
+raw_input(struct pbuf *p, struct netif *inp)
+{
+  struct raw_pcb *pcb;
+  struct ip_hdr *iphdr;
+  int proto;
+  int rc = 0;
+
+  iphdr = p->payload;
+  proto = IPH_PROTO(iphdr);
+
+  for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
+    if (pcb->protocol == proto) {
+      if (pcb->recv) {
+        if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
+          return 0;
+      }
+      pbuf_free(p);
+      rc = 1;
+      break;
+    }
+  }
+  return rc;
+}
+
+/**
+ * Bind a RAW PCB.
+ *
+ * @param pcb RAW PCB to be bound with a local address ipaddr.
+ * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
+ * bind to all local interfaces.
+ *
+ * @return lwIP error code.
+ * - ERR_OK. Successful. No error occured.
+ * - ERR_USE. The specified ipaddr is already bound to by
+ * another RAW PCB.
+ *
+ * @see raw_disconnect()
+ */
+err_t
+raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
+{
+  ip_addr_set(&pcb->local_ip, ipaddr);
+  return ERR_OK;
+}
+
+/**
+ * Connect an RAW PCB. This function is required by upper layers
+ * of lwip. Using the raw api you could use raw_send_to() instead
+ *
+ * This will associate the RAW PCB with the remote address.
+ *
+ * @param pcb RAW PCB to be connected with remote address ipaddr and port.
+ * @param ipaddr remote IP address to connect with.
+ *
+ * @return lwIP error code
+ *
+ * @see raw_disconnect() and raw_send_to()
+ */
+err_t
+raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
+{
+  ip_addr_set(&pcb->remote_ip, ipaddr);
+  return ERR_OK;
+}
+
+
+/**
+ * Set the callback function if a RAW packet with the pcb's protocol
+ * is received. If the callback function returns a value unequal 0
+ * the raw packet is "eaten" and not forwarded to any other raw pcb
+ * including lwip itself
+ */
+void
+raw_recv(struct raw_pcb *pcb,
+         int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
+                      struct ip_addr *addr),
+         void *recv_arg)
+{
+  /* remember recv() callback and user data */
+  pcb->recv = recv;
+  pcb->recv_arg = recv_arg;
+}
+
+/**
+ * Send the raw IP packet to the given address. Note that actually you cannot
+ * modify the IP headers (this is inconsitent with the receive callback where
+ * you actually get the IP headers), you can only specifiy the ip payload here.
+ * It requires some more changes in LWIP. (there will be a raw_send() function
+ * then)
+ *
+ * @param pcb the raw pcb which to send
+ * @param p the ip payload to send
+ * @param ipaddr the destination address of the whole IP packet
+ *
+ */
+err_t
+raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
+{
+  err_t err;
+  struct netif *netif;
+  struct ip_addr *src_ip;
+  struct pbuf *q; /* q will be sent down the stack */
+  
+  LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n"));
+  
+  /* not enough space to add an IP header to first pbuf in given p chain? */
+  if (pbuf_header(p, IP_HLEN)) {
+    /* allocate header in new pbuf */
+    q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
+    /* new header pbuf could not be allocated? */
+    if (q == NULL) {
+      LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n"));
+      return ERR_MEM;
+    }
+    /* chain header q in front of given pbuf p */
+    pbuf_chain(q, p);
+    /* { first pbuf q points to header pbuf } */
+    LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
+  }  else {
+    /* first pbuf q equals given pbuf */
+    q = p;
+    pbuf_header(q, -IP_HLEN);
+  }
+  
+  if ((netif = ip_route(ipaddr)) == NULL) {
+    LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr));
+#if RAW_STATS
+    /*    ++lwip_stats.raw.rterr;*/
+#endif /* RAW_STATS */
+    if (q != p) {
+      pbuf_free(q);
+    }
+    return ERR_RTE;
+  }
+
+  if (ip_addr_isany(&pcb->local_ip)) {
+    /* use outgoing network interface IP address as source address */
+    src_ip = &(netif->ip_addr);
+  } else {
+    /* use RAW PCB local IP address as source address */
+    src_ip = &(pcb->local_ip);
+  }
+
+  err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
+
+  /* did we chain a header earlier? */
+  if (q != p) {
+    /* free the header */
+    pbuf_free(q);
+  }
+  return err;
+}
+
+/**
+ * Send the raw IP packet to the address given by raw_connect()
+ *
+ * @param pcb the raw pcb which to send
+ * @param p the ip payload to send
+ * @param ipaddr the destination address of the whole IP packet
+ *
+ */
+err_t
+raw_send(struct raw_pcb *pcb, struct pbuf *p)
+{
+  return raw_send_to(pcb,p,&pcb->remote_ip);
+}
+
+/**
+ * Remove an RAW PCB.
+ *
+ * @param pcb RAW PCB to be removed. The PCB is removed from the list of
+ * RAW PCB's and the data structure is freed from memory.
+ *
+ * @see raw_new()
+ */
+void
+raw_remove(struct raw_pcb *pcb)
+{
+  struct raw_pcb *pcb2;
+  /* pcb to be removed is first in list? */
+  if (raw_pcbs == pcb) {
+    /* make list start at 2nd pcb */
+    raw_pcbs = raw_pcbs->next;
+  /* pcb not 1st in list */
+  } else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
+    /* find pcb in raw_pcbs list */
+    if (pcb2->next != NULL && pcb2->next == pcb) {
+      /* remove pcb from list */
+      pcb2->next = pcb->next;
+    }
+  }
+  memp_free(MEMP_RAW_PCB, pcb);
+}
+
+/**
+ * Create a RAW PCB.
+ *
+ * @return The RAW PCB which was created. NULL if the PCB data structure
+ * could not be allocated.
+ *
+ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
+ *
+ * @see raw_remove()
+ */
+struct raw_pcb *
+raw_new(u16_t proto) {
+  struct raw_pcb *pcb;
+
+  LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
+
+  pcb = memp_malloc(MEMP_RAW_PCB);
+  /* could allocate RAW PCB? */
+  if (pcb != NULL) {
+    /* initialize PCB to all zeroes */
+    memset(pcb, 0, sizeof(struct raw_pcb));
+    pcb->protocol = proto;
+    pcb->ttl = RAW_TTL;
+    pcb->next = raw_pcbs;
+    raw_pcbs = pcb;
+  }
+
+  return pcb;
+}
+
+#endif /* LWIP_RAW */
index 3b3f48713f12de763762f9649ff102c565b1ec69..85ebda4dff469de6fa5089d00a31b866b64fc500 100644 (file)
 
 #if LWIP_STATS
 struct stats_ lwip_stats;
-/*-----------------------------------------------------------------------------------*/
+
 void
 stats_init(void)
 {
   memset(&lwip_stats, 0, sizeof(struct stats_));
 }
 #endif /* LWIP_STATS */
-/*-----------------------------------------------------------------------------------*/
+
index a99256bed20fac68eadddb9335e258db8f21d711..cc4aaf07e7d08514887d6c5ee4b035f7c5337144 100644 (file)
@@ -44,7 +44,7 @@ struct sswt_cb
 };
 
 
-/*-----------------------------------------------------------------------------------*/
+
 void
 sys_mbox_fetch(sys_mbox_t mbox, void **msg)
 {
@@ -96,7 +96,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
 
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 sys_sem_wait(sys_sem_t sem)
 {
@@ -152,7 +152,7 @@ sys_sem_wait(sys_sem_t sem)
 
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
 {
@@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
 /* Go through timeout list (for this task only) and remove the first matching entry,
    even though the timeout has not triggered yet.
 */
-/*-----------------------------------------------------------------------------------*/
+
 void
 sys_untimeout(sys_timeout_handler h, void *arg)
 {
@@ -238,7 +238,7 @@ sys_untimeout(sys_timeout_handler h, void *arg)
 
 
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 sswt_handler(void *arg)
 {
@@ -252,7 +252,7 @@ sswt_handler(void *arg)
 /* Wait for a semaphore with timeout (specified in ms) */
 /* timeout = 0: wait forever */
 /* Returns 0 on timeout. 1 otherwise */
-/*-----------------------------------------------------------------------------------*/
+
 int
 sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
 {
@@ -279,7 +279,7 @@ sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
 
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 void
 sys_msleep(u32_t ms)
 {
@@ -289,6 +289,6 @@ sys_msleep(u32_t ms)
 
   sys_sem_free(delaysem);
 }
-/*-----------------------------------------------------------------------------------*/
+
 
 #endif /* NO_SYS */
index c1332500f2743ab4bf2e0d3c80d9289edef2831b..5dbd73cd1e18231d1412e2e5539fc1b002d43e26 100644 (file)
@@ -36,7 +36,7 @@
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp.c
  *
  * This file contains common functions for the TCP implementation, such as functinos
@@ -44,7 +44,7 @@
  * related to input and output is found in tcp_input.c and tcp_output.c respectively.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 
 #include "lwip/opt.h"
@@ -74,13 +74,13 @@ static u8_t tcp_timer;
 
 static u16_t tcp_new_port(void);
 
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_init():
  *
  * Initializes the TCP layer.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_init(void)
 {
@@ -95,41 +95,34 @@ tcp_init(void)
   tcp_timer = 0;
   
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_tmr():
  *
  * Called periodically to dispatch TCP timers.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_tmr(void)
 {
-  ++tcp_timer;
-  if (tcp_timer == 10) {
-    tcp_timer = 0;
-  }
-  
-  if (tcp_timer & 1) {
-    /* Call tcp_fasttmr() every 200 ms, i.e., every other timer
-       tcp_tmr() is called. */
-    tcp_fasttmr();
-  }
-  if (tcp_timer == 0 || tcp_timer == 5) {
-    /* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
+  /* Call tcp_fasttmr() every 250 ms */
+  tcp_fasttmr();
+
+  if (++tcp_timer & 1) {
+    /* Call tcp_tmr() every 500 ms, i.e., every other timer
        tcp_tmr() is called. */
     tcp_slowtmr();
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_close():
  *
  * Closes the connection held by the PCB.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_close(struct tcp_pcb *pcb)
 {
@@ -183,7 +176,7 @@ tcp_close(struct tcp_pcb *pcb)
   }
   return err;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_abort()
  *
@@ -192,7 +185,7 @@ tcp_close(struct tcp_pcb *pcb)
  * killed because of shortage of memory.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_abort(struct tcp_pcb *pcb)
 {
@@ -240,7 +233,7 @@ tcp_abort(struct tcp_pcb *pcb)
     tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_bind():
  *
@@ -249,16 +242,19 @@ tcp_abort(struct tcp_pcb *pcb)
  * the outgoing network interface is used instead.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
 {
   struct tcp_pcb *cpcb;
+#ifdef SO_REUSE
+  int reuse_port_all_set = 1;
+#endif /* SO_REUSE */
 
   if (port == 0) {
     port = tcp_new_port();
   }
-
+#ifndef SO_REUSE
   /* Check if the address already is in use. */
   for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
       cpcb != NULL; cpcb = cpcb->next) {
@@ -280,6 +276,102 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
       }
     }
   }
+#else /* SO_REUSE */
+  /* Search through list of PCB's in LISTEN state. 
+     
+  If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
+  or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to 
+  the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
+  But no two PCB's bound to same local port and same local address is valid.
+  
+  If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then 
+  all PCB's must have the SOF_REUSEPORT option set.
+  
+  When the two options aren't set and specified port is already bound, ERR_USE is returned saying that 
+  address is already in use. */
+  for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
+    if(cpcb->local_port == port) {
+      if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+        if(pcb->so_options & SOF_REUSEPORT) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
+          reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
+        }
+        else {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
+          return ERR_USE;
+        }
+      }
+      else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
+              (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
+        if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
+          return ERR_USE;
+        }      
+        else {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
+        }     
+      }
+    }
+  }
+
+  /* Search through list of PCB's in a state in which they can accept or send data. Same decription as for 
+     PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
+  for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
+    if(cpcb->local_port == port) {
+      if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+        if(pcb->so_options & SOF_REUSEPORT) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
+          reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
+        }
+        else {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
+          return ERR_USE;
+        }
+      }
+      else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
+              (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
+        if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
+          return ERR_USE;
+        }   
+        else {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
+        }        
+      }
+    }
+  }
+
+  /* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port} 
+     can be rebound. The same applies when SOF_REUSEPORT is set. 
+     
+     If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then 
+     all PCB's must have the SOF_REUSEPORT option set.
+     
+     When the two options aren't set and specified port is already bound, ERR_USE is returned saying that 
+     address is already in use. */
+  for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
+    if(cpcb->local_port == port) {
+      if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+        if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
+          return ERR_USE;
+        }
+        else if(pcb->so_options & SOF_REUSEPORT) {
+          LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
+          reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
+        }
+      }
+    }
+  }
+
+  /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then 
+     {IP, port} can't be reused. */
+  if(!reuse_port_all_set) {
+    LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
+    return ERR_USE;
+  }
+#endif /* SO_REUSE */
+
   if (!ip_addr_isany(ipaddr)) {
     pcb->local_ip = *ipaddr;
   }
@@ -298,7 +390,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
   return ERR_ABRT;
 }
 #endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_listen():
  *
@@ -308,7 +400,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
  * connection to LISTEN is an irreversible process.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 struct tcp_pcb *
 tcp_listen(struct tcp_pcb *pcb)
 {
@@ -325,6 +417,10 @@ tcp_listen(struct tcp_pcb *pcb)
   lpcb->callback_arg = pcb->callback_arg;
   lpcb->local_port = pcb->local_port;
   lpcb->state = LISTEN;
+  lpcb->so_options = pcb->so_options;
+  lpcb->so_options |= SOF_ACCEPTCONN;
+  lpcb->ttl = pcb->ttl;
+  lpcb->tos = pcb->tos;
   ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
   memp_free(MEMP_TCP_PCB, pcb);
 #if LWIP_CALLBACK_API
@@ -333,7 +429,7 @@ tcp_listen(struct tcp_pcb *pcb)
   TCP_REG(&tcp_listen_pcbs, lpcb);
   return (struct tcp_pcb *)lpcb;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_recved():
  *
@@ -342,13 +438,14 @@ tcp_listen(struct tcp_pcb *pcb)
  * when the data has been processed.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_recved(struct tcp_pcb *pcb, u16_t len)
 {
-  pcb->rcv_wnd += len;
-  if (pcb->rcv_wnd > TCP_WND) {
+  if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
     pcb->rcv_wnd = TCP_WND;
+  } else {
+    pcb->rcv_wnd += len;
   }
   if (!(pcb->flags & TF_ACK_DELAY) &&
      !(pcb->flags & TF_ACK_NOW)) {
@@ -358,14 +455,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
          len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_new_port():
  *
  * A nastly hack featuring 'goto' statements that allocates a
  * new TCP local port.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static u16_t
 tcp_new_port(void)
 {
@@ -398,7 +495,7 @@ tcp_new_port(void)
   }
   return port;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_connect():
  *
@@ -406,7 +503,7 @@ tcp_new_port(void)
  * argument will be called when the connection has been established.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
       err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
@@ -453,7 +550,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
   }
   return ret;
 } 
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_slowtmr():
  *
@@ -461,7 +558,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
  * removes PCBs that have been in TIME-WAIT for enough time. It also increments
  * various timers such as the inactivity timer in each PCB.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_slowtmr(void)
 {
@@ -527,6 +624,21 @@ tcp_slowtmr(void)
       }
     }
 
+   /* Check if KEEPALIVE should be sent */
+   if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
+      if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)  {
+         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
+                                 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
+                                 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
+
+         tcp_abort(pcb);
+      }
+      else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
+         tcp_keepalive(pcb);
+         pcb->keep_cnt++;
+      }
+   }
+
     /* If this PCB has queued out of sequence data, but has been
        inactive for too long, will drop the data (it will eventually
        be retransmitted). */
@@ -622,13 +734,13 @@ tcp_slowtmr(void)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_fasttmr():
  *
- * Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
+ * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_fasttmr(void)
 {
@@ -643,75 +755,72 @@ tcp_fasttmr(void)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_segs_free():
  *
  * Deallocates a list of TCP segments (tcp_seg structures).
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 u8_t
 tcp_segs_free(struct tcp_seg *seg)
 {
   u8_t count = 0;
   struct tcp_seg *next;
- again:  
-  if (seg != NULL) {
+  while (seg != NULL) {
     next = seg->next;
     count += tcp_seg_free(seg);
     seg = next;
-    goto again;
   }
   return count;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_seg_free():
  *
  * Frees a TCP segment.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 u8_t
 tcp_seg_free(struct tcp_seg *seg)
 {
   u8_t count = 0;
   
   if (seg != NULL) {
-    if (seg->p == NULL) {
-      memp_free(MEMP_TCP_SEG, seg);
-    } else {
+    if (seg->p != NULL) {
       count = pbuf_free(seg->p);
 #if TCP_DEBUG
       seg->p = NULL;
 #endif /* TCP_DEBUG */
-      memp_free(MEMP_TCP_SEG, seg);
     }
+    memp_free(MEMP_TCP_SEG, seg);
   }
   return count;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_setprio():
  *
  * Sets the priority of a connection.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
 {
   pcb->prio = prio;
 }
-/*-----------------------------------------------------------------------------------*/
+#if TCP_QUEUE_OOSEQ
+
 /*
  * tcp_seg_copy():
  *
  * Returns a copy of the given TCP segment.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
+
 struct tcp_seg *
 tcp_seg_copy(struct tcp_seg *seg)
 {
@@ -725,7 +834,8 @@ tcp_seg_copy(struct tcp_seg *seg)
   pbuf_ref(cseg->p);
   return cseg;
 }
-/*-----------------------------------------------------------------------------------*/
+#endif
+
 #if LWIP_CALLBACK_API
 static err_t
 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
@@ -739,7 +849,7 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
   return ERR_OK;
 }
 #endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcp_kill_prio(u8_t prio)
 {
@@ -770,7 +880,7 @@ tcp_kill_prio(u8_t prio)
   }      
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcp_kill_timewait(void)
 {
@@ -792,8 +902,8 @@ tcp_kill_timewait(void)
   }      
 }
 
-/*-----------------------------------------------------------------------------------*/
-/*-----------------------------------------------------------------------------------*/
+
+
 struct tcp_pcb *
 tcp_alloc(u8_t prio)
 {
@@ -817,6 +927,8 @@ tcp_alloc(u8_t prio)
     pcb->snd_buf = TCP_SND_BUF;
     pcb->snd_queuelen = 0;
     pcb->rcv_wnd = TCP_WND;
+    pcb->tos = 0;
+    pcb->ttl = TCP_TTL;
     pcb->mss = TCP_MSS;
     pcb->rto = 3000 / TCP_SLOW_INTERVAL;
     pcb->sa = 0;
@@ -836,10 +948,14 @@ tcp_alloc(u8_t prio)
 #if LWIP_CALLBACK_API
     pcb->recv = tcp_recv_null;
 #endif /* LWIP_CALLBACK_API */  
+    
+    /* Init KEEPALIVE timer */
+    pcb->keepalive = TCP_KEEPDEFAULT;
+    pcb->keep_cnt = 0;
   }
   return pcb;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_new():
  *
@@ -847,13 +963,13 @@ tcp_alloc(u8_t prio)
  * any of the TCP PCB lists.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 struct tcp_pcb *
 tcp_new(void)
 {
   return tcp_alloc(TCP_PRIO_NORMAL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_arg():
  *
@@ -861,13 +977,14 @@ tcp_new(void)
  * functions.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_arg(struct tcp_pcb *pcb, void *arg)
 {  
   pcb->callback_arg = arg;
 }
-/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+
 /*
  * tcp_recv():
  *
@@ -875,16 +992,14 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
  * connection receives data.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
-#if LWIP_CALLBACK_API
+
 void
 tcp_recv(struct tcp_pcb *pcb,
    err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
 {
   pcb->recv = recv;
 }
-#endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_sent():
  *
@@ -892,16 +1007,14 @@ tcp_recv(struct tcp_pcb *pcb,
  * has been successfully delivered to the remote host.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
-#if LWIP_CALLBACK_API
+
 void
 tcp_sent(struct tcp_pcb *pcb,
    err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
 {
   pcb->sent = sent;
 }
-#endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_err():
  *
@@ -909,16 +1022,31 @@ tcp_sent(struct tcp_pcb *pcb,
  * has occured on the connection.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
-#if LWIP_CALLBACK_API
+
 void
 tcp_err(struct tcp_pcb *pcb,
    void (* errf)(void *arg, err_t err))
 {
   pcb->errf = errf;
 }
+
+/*
+ * tcp_accept():
+ *
+ * Used for specifying the function that should be called when a
+ * LISTENing connection has been connected to another host.
+ *
+ */ 
+
+void
+tcp_accept(struct tcp_pcb *pcb,
+     err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
+{
+  ((struct tcp_pcb_listen *)pcb)->accept = accept;
+}
 #endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
+
 /*
  * tcp_poll():
  *
@@ -927,7 +1055,7 @@ tcp_err(struct tcp_pcb *pcb,
  * timer interval, which is called twice a second.
  *
  */ 
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_poll(struct tcp_pcb *pcb,
    err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
@@ -937,31 +1065,14 @@ tcp_poll(struct tcp_pcb *pcb,
 #endif /* LWIP_CALLBACK_API */  
   pcb->pollinterval = interval;
 }
-/*-----------------------------------------------------------------------------------*/
-/*
- * tcp_accept():
- *
- * Used for specifying the function that should be called when a
- * LISTENing connection has been connected to another host.
- *
- */ 
-/*-----------------------------------------------------------------------------------*/
-#if LWIP_CALLBACK_API
-void
-tcp_accept(struct tcp_pcb *pcb,
-     err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
-{
-  ((struct tcp_pcb_listen *)pcb)->accept = accept;
-}
-#endif /* LWIP_CALLBACK_API */
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_pcb_purge():
  *
  * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_pcb_purge(struct tcp_pcb *pcb)
 {
@@ -996,14 +1107,14 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
       NULL;
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_pcb_remove():
  *
  * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
 {
@@ -1022,14 +1133,14 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
 
   LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_next_iss():
  *
  * Calculates a new initial sequence number for new connections.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 u32_t
 tcp_next_iss(void)
 {
@@ -1038,31 +1149,31 @@ tcp_next_iss(void)
   iss += tcp_ticks;       /* XXX */
   return iss;
 }
-/*-----------------------------------------------------------------------------------*/
+
 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
 void
 tcp_debug_print(struct tcp_hdr *tcphdr)
 {
   LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(TCP_DEBUG, ("|      %04x     |      %04x     | (src port, dest port)\n",
-         tcphdr->src, tcphdr->dest));
+  LWIP_DEBUGF(TCP_DEBUG, ("|    %5u      |    %5u      | (src port, dest port)\n",
+         ntohs(tcphdr->src), ntohs(tcphdr->dest)));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(TCP_DEBUG, ("|            %08lu           | (seq no)\n",
-          tcphdr->seqno));
+  LWIP_DEBUGF(TCP_DEBUG, ("|           %010lu          | (seq no)\n",
+          ntohl(tcphdr->seqno)));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(TCP_DEBUG, ("|            %08lu           | (ack no)\n",
-         tcphdr->ackno));
+  LWIP_DEBUGF(TCP_DEBUG, ("|           %010lu          | (ack no)\n",
+         ntohl(tcphdr->ackno)));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(TCP_DEBUG, ("| %2u |    |%u%u%u%u%u|    %5u      | (offset, flags (",
-       TCPH_OFFSET(tcphdr),
-         TCPH_FLAGS(tcphdr) >> 4 & 1,
+  LWIP_DEBUGF(TCP_DEBUG, ("| %2u |   |%u%u%u%u%u%u|     %5u     | (hdrlen, flags (",
+       TCPH_HDRLEN(tcphdr),
+         TCPH_FLAGS(tcphdr) >> 5 & 1,
          TCPH_FLAGS(tcphdr) >> 4 & 1,
          TCPH_FLAGS(tcphdr) >> 3 & 1,
          TCPH_FLAGS(tcphdr) >> 2 & 1,
          TCPH_FLAGS(tcphdr) >> 1 & 1,
          TCPH_FLAGS(tcphdr) & 1,
-         tcphdr->wnd));
+         ntohs(tcphdr->wnd)));
   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
   LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@@ -1070,7 +1181,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
          ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
   LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_debug_print_state(enum tcp_state s)
 {
@@ -1111,7 +1222,7 @@ tcp_debug_print_state(enum tcp_state s)
    break;
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_debug_print_flags(u8_t flags)
 {
@@ -1133,8 +1244,14 @@ tcp_debug_print_flags(u8_t flags)
   if (flags & TCP_URG) {
     LWIP_DEBUGF(TCP_DEBUG, ("URG "));
   }
+  if (flags & TCP_ECE) {
+    LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
+  }
+  if (flags & TCP_CWR) {
+    LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
+  }
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_debug_print_pcbs(void)
 {
@@ -1161,7 +1278,7 @@ tcp_debug_print_pcbs(void)
     tcp_debug_print_state(pcb->state);
   }    
 }
-/*-----------------------------------------------------------------------------------*/
+
 int
 tcp_pcbs_sane(void)
 {
@@ -1178,7 +1295,7 @@ tcp_pcbs_sane(void)
 }
 #endif /* TCP_DEBUG */
 #endif /* LWIP_TCP */
-/*-----------------------------------------------------------------------------------*/
+
 
 
 
index 73e4010deb6f90b8041ad9d48bf3b9243e75f30e..ba88c9632ac04fa6dfdcd8a21fba9ac3aa09cdfd 100644 (file)
@@ -36,7 +36,7 @@
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_input.c
  *
  * The input processing functions of TCP.
@@ -45,7 +45,7 @@
  * tcp_process() -> tcp_receive() (-> application).
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 
 #include "lwip/def.h"
@@ -85,7 +85,7 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
 
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_input:
  *
  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
@@ -93,34 +93,38 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
  * the TCP finite state machine. This function is called by the IP layer (in
  * ip_input()).
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_input(struct pbuf *p, struct netif *inp)
 {
   struct tcp_pcb *pcb, *prev;
   struct tcp_pcb_listen *lpcb;
-  u8_t offset;
+  u8_t hdrlen;
   err_t err;
 
+#ifdef SO_REUSE
+  struct tcp_pcb *pcb_temp;
+  int reuse = 0;
+  int reuse_port = 0;
+#endif /* SO_REUSE */
 
   PERF_START;
 
-
-#ifdef TCP_STATS
-  ++lwip_stats.tcp.recv;
-#endif /* TCP_STATS */
+  TCP_STATS_INC(tcp.recv);
 
   iphdr = p->payload;
   tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
 
+#if TCP_INPUT_DEBUG
+  tcp_debug_print(tcphdr);
+#endif
+
   /* remove header from payload */
   if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
     /* drop short packets */
     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
-#ifdef TCP_STATS
-    ++lwip_stats.tcp.lenerr;
-    ++lwip_stats.tcp.drop;
-#endif /* TCP_STATS */
+    TCP_STATS_INC(tcp.lenerr);
+    TCP_STATS_INC(tcp.drop);
     pbuf_free(p);
     return;
   }
@@ -142,10 +146,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
 #if TCP_DEBUG
     tcp_debug_print(tcphdr);
 #endif /* TCP_DEBUG */
-#ifdef TCP_STATS
-    ++lwip_stats.tcp.chkerr;
-    ++lwip_stats.tcp.drop;
-#endif /* TCP_STATS */
+    TCP_STATS_INC(tcp.chkerr);
+    TCP_STATS_INC(tcp.drop);
 
     pbuf_free(p);
     return;
@@ -154,8 +156,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
 
   /* Move the payload pointer in the pbuf so that it points to the
      TCP data instead of the TCP header. */
-  offset = TCPH_OFFSET(tcphdr) >> 4;
-  pbuf_header(p, -(offset * 4));
+  hdrlen = TCPH_HDRLEN(tcphdr);
+  pbuf_header(p, -(hdrlen * 4));
 
   /* Convert fields in TCP header to host byte order. */
   tcphdr->src = ntohs(tcphdr->src);
@@ -170,7 +172,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
   /* Demultiplex an incoming segment. First, we check if it is destined
      for an active connection. */
   prev = NULL;
+
+#ifdef SO_REUSE
+  pcb_temp = tcp_active_pcbs;
+  
+ again_1:
+  
+  /* Iterate through the TCP pcb list for a fully matching pcb */
+  for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
+#else  /* SO_REUSE */
   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+#endif  /* SO_REUSE */
     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);
@@ -179,6 +191,32 @@ tcp_input(struct pbuf *p, struct netif *inp)
        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
 
+#ifdef SO_REUSE
+      if(pcb->so_options & SOF_REUSEPORT) {
+        if(reuse) {
+          /* We processed one PCB already */
+          LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
+        } else {
+          /* First PCB with this address */
+          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
+          reuse = 1;
+        }
+        
+        reuse_port = 1; 
+        p->ref++;
+        
+        /* We want to search on next socket after receiving */
+        pcb_temp = pcb->next;
+        
+        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
+      } else  {
+        if(reuse) {
+          /* We processed one PCB already */
+          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
+        }
+      }
+#endif /* SO_REUSE */
+
       /* Move this PCB to the front of the list so that subsequent
    lookups will be faster (we exploit locality in TCP segment
    arrivals). */
@@ -323,33 +361,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
     tcp_debug_print_state(pcb->state);
 #endif /* TCP_DEBUG */
 #endif /* TCP_INPUT_DEBUG */
+#ifdef SO_REUSE
+    /* First socket should receive now */
+    if(reuse_port) {
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
+      reuse_port = 0;
+      
+      /* We are searching connected sockets */
+      goto again_1;
+    }
+#endif /* SO_REUSE */
 
   } else {
+#ifdef SO_REUSE
+    if(reuse) {
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
+      pbuf_free(p);
+      goto end;
+    }
+#endif /* SO_REUSE */
     /* 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)) {
-#ifdef TCP_STATS
-      ++lwip_stats.tcp.proterr;
-      ++lwip_stats.tcp.drop;
-#endif /* TCP_STATS */
+      TCP_STATS_INC(tcp.proterr);
+      TCP_STATS_INC(tcp.drop);
       tcp_rst(ackno, seqno + tcplen,
         &(iphdr->dest), &(iphdr->src),
         tcphdr->dest, tcphdr->src);
     }
     pbuf_free(p);
   }
-
+#ifdef SO_REUSE
+ end:
+#endif /* SO_REUSE */
   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
   PERF_STOP("tcp_input");
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_listen_input():
  *
  * Called by tcp_input() when a segment arrives for a listening
  * connection.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 tcp_listen_input(struct tcp_pcb_listen *pcb)
 {
@@ -373,9 +428,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
        SYN at a time when we have more memory available. */
     if (npcb == NULL) {
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
-#ifdef TCP_STATS
-      ++lwip_stats.tcp.memerr;
-#endif /* TCP_STATS */
+      TCP_STATS_INC(tcp.memerr);
       return ERR_MEM;
     }
     /* Set up the new PCB. */
@@ -387,12 +440,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
     npcb->rcv_nxt = seqno + 1;
     npcb->snd_wnd = tcphdr->wnd;
     npcb->ssthresh = npcb->snd_wnd;
-    npcb->snd_wl1 = seqno;
+    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
     npcb->callback_arg = pcb->callback_arg;
 #if LWIP_CALLBACK_API
     npcb->accept = pcb->accept;
 #endif /* LWIP_CALLBACK_API */
-
+    /* inherit socket options */
+    npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
     /* Register the new PCB so that we can begin receiving segments
        for it. */
     TCP_REG(&tcp_active_pcbs, npcb);
@@ -411,13 +465,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
   }
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_timewait_input():
  *
  * Called by tcp_input() when a segment arrives for a connection in
  * TIME_WAIT.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 tcp_timewait_input(struct tcp_pcb *pcb)
 {
@@ -429,7 +483,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
   }
   return tcp_output(pcb);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_process
  *
  * Implements the TCP state machine. Called by tcp_input. In some
@@ -437,7 +491,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
  * argument will be freed by the caller (tcp_input()) unless the
  * recv_data pointer in the pcb is set.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 tcp_process(struct tcp_pcb *pcb)
 {
@@ -479,6 +533,7 @@ tcp_process(struct tcp_pcb *pcb)
 
   /* Update the PCB (in)activity timer. */
   pcb->tmr = tcp_ticks;
+  pcb->keep_cnt = 0;
 
   /* Do different things depending on the TCP state. */
   switch (pcb->state) {
@@ -489,7 +544,8 @@ tcp_process(struct tcp_pcb *pcb)
        ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
       pcb->rcv_nxt = seqno + 1;
       pcb->lastack = ackno;
-      pcb->snd_wnd = pcb->snd_wl1 = tcphdr->wnd;
+      pcb->snd_wnd = tcphdr->wnd;
+      pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
       pcb->state = ESTABLISHED;
       pcb->cwnd = pcb->mss;
       --pcb->snd_queuelen;
@@ -594,7 +650,7 @@ tcp_process(struct tcp_pcb *pcb)
 
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_receive:
  *
  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
@@ -606,7 +662,7 @@ tcp_process(struct tcp_pcb *pcb)
  * If the incoming segment constitutes an ACK for a segment that was used for RTT
  * estimation, the RTT is estimated here as well.
  */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcp_receive(struct tcp_pcb *pcb)
 {
@@ -934,7 +990,7 @@ tcp_receive(struct tcp_pcb *pcb)
     inseg.p = NULL;
   }
   if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
-    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
+    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
     recv_flags = TF_GOT_FIN;
   }
 
@@ -957,15 +1013,14 @@ tcp_receive(struct tcp_pcb *pcb)
       /* Chain this pbuf onto the pbuf that we will pass to
          the application. */
       if (recv_data) {
-              pbuf_chain(recv_data, cseg->p);
-              pbuf_free(cseg->p);
+              pbuf_cat(recv_data, cseg->p);
             } else {
         recv_data = cseg->p;
       }
       cseg->p = NULL;
     }
     if (flags & TCP_FIN) {
-      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
       recv_flags = TF_GOT_FIN;
     }
 
@@ -1103,7 +1158,7 @@ tcp_receive(struct tcp_pcb *pcb)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * tcp_parseopt:
  *
@@ -1111,7 +1166,7 @@ tcp_receive(struct tcp_pcb *pcb)
  * from uIP with only small changes.)
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcp_parseopt(struct tcp_pcb *pcb)
 {
@@ -1122,8 +1177,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
   opts = (u8_t *)tcphdr + TCP_HLEN;
 
   /* Parse the TCP MSS option, if present. */
-  if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
-    for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
+  if(TCPH_HDRLEN(tcphdr) > 0x5) {
+    for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
       opt = opts[c];
       if (opt == 0x00) {
         /* End of options. */
@@ -1153,5 +1208,5 @@ tcp_parseopt(struct tcp_pcb *pcb)
   }
 }
 #endif /* LWIP_TCP */
-/*-----------------------------------------------------------------------------------*/
+
 
index d323bf349f020f66ab91cacfdfa66fd6a82c1aa5..3adab4c6274cdee7d615c6137effe679adb9278d 100644 (file)
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* tcp_output.c
  *
  * The output functions of TCP.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 
 #include "lwip/def.h"
 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
 
 
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
 {
   return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
 
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
 {
@@ -90,7 +90,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
     return ERR_CONN;
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
       u8_t flags, u8_t copy,
@@ -154,12 +154,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
     seg->p = NULL;
 
     if (queue == NULL) {
-      queue = seg;
+      useg = queue = seg;
     }
     else {
       /* Attach the segment to the end of the queued segments. */
-      for (useg = queue; useg->next != NULL; useg = useg->next);
       useg->next = seg;
+      useg = seg;
     }
 
     /* If copy is set, memory should be allocated
@@ -210,9 +210,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
       }
       ++queuelen;
 
-      /* Chain the headers and data pbufs together. */
-      pbuf_chain(seg->p, p);
-      pbuf_free(p);
+      /* Concatenate the headers and data pbufs together. */
+      pbuf_cat(seg->p, p);
       p = NULL;
     }
 
@@ -234,9 +233,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
 
       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
 
-#ifdef TCP_STATS
-      ++lwip_stats.tcp.err;
-#endif /* TCP_STATS */
+      TCP_STATS_INC(tcp.err);
       goto memerr;
     }
     seg->tcphdr = seg->p->payload;
@@ -249,10 +246,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
 
     /* Copy the options into the header, if they are present. */
     if (optdata == NULL) {
-      TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
+      TCPH_HDRLEN_SET(seg->tcphdr, 5);
     }
     else {
-      TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
+      TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
       /* Copy options into data portion of segment.
        Options can thus only be sent in non data carrying
        segments such as SYN|ACK. */
@@ -288,11 +285,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
     useg->len + queue->len <= pcb->mss) {
     /* Remove TCP header from first segment. */
     pbuf_header(queue->p, -TCP_HLEN);
-    pbuf_chain(useg->p, queue->p);
-    /* Free buffer which was merged. Note that the previous pbuf_chain call
-     * will have incremented the ref count, so here the ref count will still
-     * be 1 for the 1 pointer still being used on this buffer. */
-    pbuf_free(queue->p);
+    pbuf_cat(useg->p, queue->p);
     useg->len += queue->len;
     useg->next = queue->next;
 
@@ -327,14 +320,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
   /* Set the PSH flag in the last segment that we enqueued, but only
   if the segment has data (indicated by seglen > 0). */
   if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
-    TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
+    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
   }
 
   return ERR_OK;
   memerr:
-#ifdef TCP_STATS
-  ++lwip_stats.tcp.memerr;
-#endif /* TCP_STATS */
+  TCP_STATS_INC(tcp.memerr);
 
   if (queue != NULL) {
     tcp_segs_free(queue);
@@ -347,7 +338,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
   LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
   return ERR_MEM;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /* find out what we can send and send it */
 err_t
 tcp_output(struct tcp_pcb *pcb)
@@ -373,6 +364,13 @@ tcp_output(struct tcp_pcb *pcb)
 
   seg = pcb->unsent;
 
+  /* useg should point to last segment on unacked queue */
+  useg = pcb->unacked;
+  if (useg != NULL) {
+    for (; useg->next != NULL; useg = useg->next);
+  }                                                                             
+
+   
   /* If the TF_ACK_NOW flag is set, we check if there is data that is
      to be sent. If data is to be sent out, we'll just piggyback our
      acknowledgement with the outgoing segment. If no data will be
@@ -398,13 +396,14 @@ tcp_output(struct tcp_pcb *pcb)
     TCPH_FLAGS_SET(tcphdr, TCP_ACK);
     tcphdr->wnd = htons(pcb->rcv_wnd);
     tcphdr->urgp = 0;
-    TCPH_OFFSET_SET(tcphdr, 5 << 4);
+    TCPH_HDRLEN_SET(tcphdr, 5);
 
     tcphdr->chksum = 0;
     tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
           IP_PROTO_TCP, p->tot_len);
 
-    ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
+
+    ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
         IP_PROTO_TCP);
     pbuf_free(p);
 
@@ -443,7 +442,7 @@ tcp_output(struct tcp_pcb *pcb)
     pcb->unsent = seg->next;
 
     if (pcb->state != SYN_SENT) {
-      TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
+      TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
     }
 
@@ -457,11 +456,10 @@ tcp_output(struct tcp_pcb *pcb)
       seg->next = NULL;
       if (pcb->unacked == NULL) {
         pcb->unacked = seg;
-
-
+        useg = seg;
       } else {
-        for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
         useg->next = seg;
+        useg = useg->next;
       }
     } else {
       tcp_seg_free(seg);
@@ -470,7 +468,7 @@ tcp_output(struct tcp_pcb *pcb)
   }
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
 {
@@ -523,14 +521,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
              &(pcb->local_ip),
              &(pcb->remote_ip),
              IP_PROTO_TCP, seg->p->tot_len);
-#ifdef TCP_STATS
-  ++lwip_stats.tcp.xmit;
-#endif /* TCP_STATS */
+  TCP_STATS_INC(tcp.xmit);
 
-  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
+  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
       IP_PROTO_TCP);
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_rst(u32_t seqno, u32_t ackno,
   struct ip_addr *local_ip, struct ip_addr *remote_ip,
@@ -552,20 +548,19 @@ tcp_rst(u32_t seqno, u32_t ackno,
   TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
   tcphdr->wnd = htons(TCP_WND);
   tcphdr->urgp = 0;
-  TCPH_OFFSET_SET(tcphdr, 5 << 4);
+  TCPH_HDRLEN_SET(tcphdr, 5);
 
   tcphdr->chksum = 0;
   tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
               IP_PROTO_TCP, p->tot_len);
 
-#ifdef TCP_STATS
-  ++lwip_stats.tcp.xmit;
-#endif /* TCP_STATS */
-  ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
+  TCP_STATS_INC(tcp.xmit);
+   /* Send output with hardcoded TTL since we have no access to the pcb */
+  ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
   pbuf_free(p);
   LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 tcp_rexmit(struct tcp_pcb *pcb)
 {
@@ -595,6 +590,48 @@ tcp_rexmit(struct tcp_pcb *pcb)
   tcp_output(pcb);
 
 }
+
+void
+tcp_keepalive(struct tcp_pcb *pcb)
+{
+   struct pbuf *p;
+   struct tcp_hdr *tcphdr;
+
+   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
+                           ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
+                           ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
+
+   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld   pcb->tmr %ld  pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
+   
+   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
+
+   if(p == NULL) {
+      LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
+      return;
+   }
+
+   tcphdr = p->payload;
+   tcphdr->src = htons(pcb->local_port);
+   tcphdr->dest = htons(pcb->remote_port);
+   tcphdr->seqno = htonl(pcb->snd_nxt - 1);
+   tcphdr->ackno = htonl(pcb->rcv_nxt);
+   tcphdr->wnd = htons(pcb->rcv_wnd);
+   tcphdr->urgp = 0;
+   TCPH_HDRLEN_SET(tcphdr, 5);
+   
+   tcphdr->chksum = 0;
+   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
+
+  TCP_STATS_INC(tcp.xmit);
+
+   /* Send output to IP */
+  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
+
+  pbuf_free(p);
+
+  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
+}
+
 #endif /* LWIP_TCP */
 
 
index b087306671bbce6ff00816b3e1df7ea3d0883756..166586b7c360a31507cc0d1d397dad5a856bb0c5 100644 (file)
  *
  */
 
-/*-----------------------------------------------------------------------------------*/
+
 /* udp.c
  *
  * The code for the User Datagram Protocol UDP.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 #include "lwip/opt.h"
 
 #include "lwip/def.h"
@@ -64,24 +64,20 @@ struct udp_pcb *udp_pcbs = NULL;
 
 static struct udp_pcb *pcb_cache = NULL;
 
-#if UDP_DEBUG
-int udp_debug_print(struct udp_hdr *udphdr);
-#endif /* UDP_DEBUG */
 
-/*-----------------------------------------------------------------------------------*/
 void
 udp_init(void)
 {
   udp_pcbs = pcb_cache = NULL;
 }
 
-/*-----------------------------------------------------------------------------------*/
+
 /* udp_lookup:
  *
  * An experimental feature that will be changed in future versions. Do
  * not depend on it yet...
  */
-/*-----------------------------------------------------------------------------------*/
+
 #ifdef LWIP_DEBUG
 u8_t
 udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
@@ -163,21 +159,24 @@ udp_input(struct pbuf *p, struct netif *inp)
   struct ip_hdr *iphdr;
   u16_t src, dest;
 
+#ifdef SO_REUSE
+  struct udp_pcb *pcb_temp;
+  int reuse = 0;
+  int reuse_port_1 = 0;
+  int reuse_port_2 = 0;
+#endif /* SO_REUSE */
+  
   PERF_START;
 
-#ifdef UDP_STATS
-  ++lwip_stats.udp.recv;
-#endif /* UDP_STATS */
+  UDP_STATS_INC(udp.recv);
 
   iphdr = p->payload;
 
   if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
     /* drop short packets */
     LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
-#ifdef UDP_STATS
-    ++lwip_stats.udp.lenerr;
-    ++lwip_stats.udp.drop;
-#endif /* UDP_STATS */
+    UDP_STATS_INC(udp.lenerr);
+    UDP_STATS_INC(udp.drop);
     snmp_inc_udpinerrors();
     pbuf_free(p);
     goto end;
@@ -190,9 +189,7 @@ udp_input(struct pbuf *p, struct netif *inp)
   src = ntohs(udphdr->src);
   dest = ntohs(udphdr->dest);
 
-#if UDP_DEBUG
   udp_debug_print(udphdr);
-#endif /* UDP_DEBUG */
 
   /* print the UDP source and destination */
   LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
@@ -200,8 +197,18 @@ udp_input(struct pbuf *p, struct netif *inp)
     ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
     ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
     ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
+
+#ifdef SO_REUSE
+  pcb_temp = udp_pcbs;
+  
+ again_1:
+  
+  /* Iterate through the UDP pcb list for a fully matching pcb */
+  for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
+#else  /* SO_REUSE */ 
   /* Iterate through the UDP pcb list for a fully matching pcb */
   for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+#endif  /* SO_REUSE */ 
     /* print the PCB local and remote address */
     LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
       ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
@@ -221,6 +228,27 @@ udp_input(struct pbuf *p, struct netif *inp)
        (ip_addr_isany(&pcb->local_ip) ||
        /* PCB local IP address matches UDP destination IP address? */
         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+#ifdef SO_REUSE
+      if(pcb->so_options & SOF_REUSEPORT) {
+        if(reuse) {
+          /* We processed one PCB already */
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
+        } else {
+          /* First PCB with this address */
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
+          reuse = 1;
+        }
+        
+        reuse_port_1 = 1; 
+        p->ref++;
+        LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
+      } else {
+        if(reuse) {
+          /* We processed one PCB already */
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
+        }
+      }
+#endif /* SO_REUSE */
       break;
     }
   }
@@ -228,7 +256,16 @@ udp_input(struct pbuf *p, struct netif *inp)
   if (pcb == NULL) {
     /* Iterate through the UDP PCB list for a pcb that matches
        the local address. */
+
+#ifdef SO_REUSE
+    pcb_temp = udp_pcbs;
+    
+  again_2:
+
+    for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
+#else  /* SO_REUSE */ 
     for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+#endif  /* SO_REUSE */ 
       LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
         ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
         ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@@ -242,7 +279,28 @@ udp_input(struct pbuf *p, struct netif *inp)
         (ip_addr_isany(&pcb->local_ip) ||
         /* ...matching interface address? */
         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
-         break;
+#ifdef SO_REUSE
+        if(pcb->so_options & SOF_REUSEPORT) {
+          if(reuse) {
+            /* We processed one PCB already */
+            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
+          } else {
+            /* First PCB with this address */
+            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
+            reuse = 1;
+          }
+          
+          reuse_port_2 = 1; 
+          p->ref++;
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
+        } else {
+          if(reuse) {
+            /* We processed one PCB already */
+            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
+          }
+        }
+#endif /* SO_REUSE */
+        break;
       }
     }
   }
@@ -262,10 +320,8 @@ udp_input(struct pbuf *p, struct netif *inp)
          (struct ip_addr *)&(iphdr->dest),
          IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
   LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
-#ifdef UDP_STATS
-  ++lwip_stats.udp.chkerr;
-  ++lwip_stats.udp.drop;
-#endif /* UDP_STATS */
+  UDP_STATS_INC(udp.chkerr);
+  UDP_STATS_INC(udp.drop);
   snmp_inc_udpinerrors();
   pbuf_free(p);
   goto end;
@@ -277,10 +333,8 @@ udp_input(struct pbuf *p, struct netif *inp)
         IP_PROTO_UDP, p->tot_len) != 0) {
     LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
 
-#ifdef UDP_STATS
-    ++lwip_stats.udp.chkerr;
-    ++lwip_stats.udp.drop;
-#endif /* UDP_STATS */
+    UDP_STATS_INC(udp.chkerr);
+    UDP_STATS_INC(udp.drop);
     snmp_inc_udpinerrors();
     pbuf_free(p);
     goto end;
@@ -291,7 +345,33 @@ udp_input(struct pbuf *p, struct netif *inp)
     if (pcb != NULL) {
       snmp_inc_udpindatagrams();
       pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
+#ifdef SO_REUSE
+      /* First socket should receive now */
+      if(reuse_port_1 || reuse_port_2) {
+        /* We want to search on next socket after receiving */
+        pcb_temp = pcb->next;
+        
+        if(reuse_port_1) {
+          /* We are searching connected sockets */
+          reuse_port_1 = 0;
+          reuse_port_2 = 0;
+          goto again_1;
+        } else {
+          /* We are searching unconnected sockets */
+          reuse_port_1 = 0;
+          reuse_port_2 = 0;
+          goto again_2;
+        }
+      }
+#endif /* SO_REUSE */ 
     } else {
+#ifdef SO_REUSE
+      if(reuse) {
+        LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
+        pbuf_free(p);
+        goto end;
+      }
+#endif /* SO_REUSE */
       LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
 
       /* No match was found, send ICMP destination port unreachable unless
@@ -304,10 +384,8 @@ udp_input(struct pbuf *p, struct netif *inp)
   p->payload = iphdr;
   icmp_dest_unreach(p, ICMP_DUR_PORT);
       }
-#ifdef UDP_STATS
-      ++lwip_stats.udp.proterr;
-      ++lwip_stats.udp.drop;
-#endif /* UDP_STATS */
+      UDP_STATS_INC(udp.proterr);
+      UDP_STATS_INC(udp.drop);
     snmp_inc_udpnoports();
       pbuf_free(p);
     }
@@ -380,9 +458,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
 
   if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
     LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
-#ifdef UDP_STATS
-    ++lwip_stats.udp.rterr;
-#endif /* UDP_STATS */
+    UDP_STATS_INC(udp.rterr);
     return ERR_RTE;
   }
   /* using IP_ANY_ADDR? */
@@ -407,7 +483,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
     /* chksum zero must become 0xffff, as zero means 'no checksum' */
     if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
     /* output to IP */
-    err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
+    err = ip_output_if (p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);    
     snmp_inc_udpoutdatagrams();
   } else {
     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@@ -422,7 +498,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
     snmp_inc_udpoutdatagrams();
     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
     /* output to IP */
-    err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);
+    err = ip_output_if(p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);    
   }
 
   /* did we chain a header earlier? */
@@ -431,9 +507,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
     pbuf_free(q);
   }
 
-#ifdef UDP_STATS
-  ++lwip_stats.udp.xmit;
-#endif /* UDP_STATS */
+  UDP_STATS_INC(udp.xmit);
   return err;
 }
 
@@ -457,9 +531,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
 {
   struct udp_pcb *ipcb;
   u8_t rebind;
+#ifdef SO_REUSE
+  int reuse_port_all_set = 1;
+#endif /* SO_REUSE */
   LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
   ip_addr_debug_print(UDP_DEBUG, ipaddr);
   LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
+
   rebind = 0;
   /* Check for double bind and rebind of the same pcb */
   for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -470,6 +548,8 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
       /* pcb already in list, just rebind */
       rebind = 1;
     }
+
+#ifndef SO_REUSE
 /* this code does not allow upper layer to share a UDP port for
    listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
    SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
@@ -486,8 +566,52 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
       return ERR_USE;
     }
 #endif
+
+#else /* SO_REUSE */
+      /* Search through list of PCB's. 
+         
+      If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
+      or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to 
+      the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
+      But no two PCB's bound to same local port and same local address is valid.
+      
+      If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then 
+      all PCB's must have the SOF_REUSEPORT option set.
+      
+      When the two options aren't set and specified port is already bound, ERR_USE is returned saying that 
+      address is already in use. */
+    else if (ipcb->local_port == port) {
+      if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
+        if(pcb->so_options & SOF_REUSEPORT) {
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
+          reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
+        }
+        else {
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
+          return ERR_USE;
+        }
+      }
+      else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
+              (!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
+        if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
+          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
+          return ERR_USE;
+        }           
+      }
+    }
+#endif /* SO_REUSE */
+
+  }
+
+#ifdef SO_REUSE
+  /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then 
+     {IP, port} can't be reused. */
+  if(!reuse_port_all_set) {
+    LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
+    return ERR_USE;
   }
-  /* bind local address */
+#endif /* SO_REUSE */
+
   ip_addr_set(&pcb->local_ip, ipaddr);
   /* no port specified? */
   if (port == 0) {
@@ -559,9 +683,7 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
 
     if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
       LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
-#ifdef UDP_STATS
-        ++lwip_stats.udp.rterr;
-#endif /* UDP_STATS */
+        UDP_STATS_INC(udp.rterr);
       return ERR_RTE;
     }
     /** TODO: this will bind the udp pcb locally, to the interface which
@@ -596,7 +718,7 @@ udp_disconnect(struct udp_pcb *pcb)
 {
   pcb->flags &= ~UDP_FLAGS_CONNECTED;
 }
-/*-----------------------------------------------------------------------------------*/
+
 void
 udp_recv(struct udp_pcb *pcb,
    void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@@ -650,9 +772,12 @@ udp_new(void) {
     /* initialize PCB to all zeroes */
     memset(pcb, 0, sizeof(struct udp_pcb));
   }
+  
+  pcb->ttl = UDP_TTL;
+  
   return pcb;
 }
-/*-----------------------------------------------------------------------------------*/
+
 #if UDP_DEBUG
 int
 udp_debug_print(struct udp_hdr *udphdr)
@@ -668,7 +793,7 @@ udp_debug_print(struct udp_hdr *udphdr)
   return 0;
 }
 #endif /* UDP_DEBUG */
-/*-----------------------------------------------------------------------------------*/
+
 #endif /* LWIP_UDP */
 
 
index 070c8d6cecfe63a6312264dec7789b2ec37f3702..57f96a28f8a292cbdbc1f3fdebd83265d642f5dc 100644 (file)
@@ -47,9 +47,9 @@ u8_t ip_lookup(void *header, struct netif *inp);
 struct netif *ip_route(struct ip_addr *dest);
 err_t ip_input(struct pbuf *p, struct netif *inp);
 err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
-    u8_t ttl, u8_t proto);
+               u8_t ttl, u8_t tos, u8_t proto);
 err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
-       u8_t ttl, u8_t proto,
+                  u8_t ttl, u8_t tos, u8_t proto,
        struct netif *netif);
 
 #define IP_HLEN 20
@@ -67,6 +67,36 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
 #endif /* IP_HDRINCL */
 #define IP_HDRINCL  NULL
 
+
+/* This is the common part of all PCB types. It needs to be at the
+   beginning of a PCB type definition. It is located here so that
+   changes to this common part are made in one location instead of
+   having to change all PCB structs. */
+#define IP_PCB struct ip_addr local_ip; \
+  struct ip_addr remote_ip; \
+   /* Socket options */  \
+  u16_t so_options;      \
+   /* Type Of Service */ \
+  u8_t tos;              \
+  /* Time To Live */     \
+  u8_t ttl
+
+/*
+ * Option flags per-socket. These are the same like SO_XXX.
+ */
+#define        SOF_DEBUG           (u16_t)0x0001U              /* turn on debugging info recording */
+#define        SOF_ACCEPTCONN  (u16_t)0x0002U          /* socket has had listen() */
+#define        SOF_REUSEADDR   (u16_t)0x0004U          /* allow local address reuse */
+#define        SOF_KEEPALIVE   (u16_t)0x0008U          /* keep connections alive */
+#define        SOF_DONTROUTE   (u16_t)0x0010U          /* just use interface addresses */
+#define        SOF_BROADCAST   (u16_t)0x0020U          /* permit sending of broadcast msgs */
+#define        SOF_USELOOPBACK (u16_t)0x0040U          /* bypass hardware when possible */
+#define        SOF_LINGER          (u16_t)0x0080U              /* linger on close if data present */
+#define        SOF_OOBINLINE   (u16_t)0x0100U          /* leave received OOB data in line */
+#define        SOF_REUSEPORT   (u16_t)0x0200U          /* allow local address & port reuse */
+
+
+
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
 #endif
@@ -117,6 +147,8 @@ PACK_STRUCT_END
 
 #if IP_DEBUG
 void ip_debug_print(struct pbuf *p);
+#else
+#define ip_debug_print(p)
 #endif /* IP_DEBUG */
 
 #endif /* __LWIP_IP_H__ */
index a4b72ea736f999c8e17e5d266eb0f01193df6c4e..6680d8d88a7829cb36df9b64d3cd8c75e73344a0 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "lwip/ip.h"
 
+#include "lwip/raw.h"
 #include "lwip/udp.h"
 #include "lwip/tcp.h"
 
@@ -50,7 +51,8 @@ enum netconn_type {
   NETCONN_TCP,
   NETCONN_UDP,
   NETCONN_UDPLITE,
-  NETCONN_UDPNOCHKSUM
+  NETCONN_UDPNOCHKSUM,
+  NETCONN_RAW
 };
 
 enum netconn_state {
@@ -82,6 +84,7 @@ struct netconn {
   union {
     struct tcp_pcb *tcp;
     struct udp_pcb *udp;
+    struct raw_pcb *raw;
   } pcb;
   err_t err;
   sys_mbox_t mbox;
@@ -121,6 +124,9 @@ struct netconn *  netconn_new     (enum netconn_type type);
 struct
 netconn *netconn_new_with_callback(enum netconn_type t,
                                    void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
+struct
+netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
+                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
 err_t             netconn_delete  (struct netconn *conn);
 enum netconn_type netconn_type    (struct netconn *conn);
 err_t             netconn_peer    (struct netconn *conn,
index 3e09dfbc62f2a761bcc97b6bec0321c54df448ee..cc9b0c55d02112a1ca0e451749492e245a17e02a 100644 (file)
 /** flag for LWIP_DEBUGF to halt after printing this debug message */
 #define DBG_HALT    0x08U
 
-#ifdef LWIP_DEBUG
-# ifndef LWIP_NOASSERT
+#ifndef LWIP_NOASSERT
 #  define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
-# else
+#else
 #  define LWIP_ASSERT(x,y) 
-# endif
+#endif
+
+#ifdef LWIP_DEBUG
 /** print debug message only if debug message type is enabled...
  *  AND is of correct type AND is at least DBG_LEVEL
  */
 #  define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && (((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
 #  define LWIP_ERROR(x)   do { LWIP_PLATFORM_DIAG(x); } while(0)  
 #else /* LWIP_DEBUG */
-#  define LWIP_ASSERT(x,y) 
 #  define LWIP_DEBUGF(debug,x) 
 #  define LWIP_ERROR(x)  
 #endif /* LWIP_DEBUG */
index f1ca270d3d6fd86c222647b4bf9fe7b0f3b93296..f9607dcfa2444016e2f261daed39ba1082dc652e 100644 (file)
@@ -49,9 +49,13 @@ void mem_free(void *mem);
 void *mem_realloc(void *mem, mem_size_t size);
 void *mem_reallocm(void *mem, mem_size_t size);
 
+#ifndef MEM_ALIGN_SIZE
 #define MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
+#endif
 
+#ifndef MEM_ALIGN
 #define MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
+#endif
 
 #endif /* __LWIP_MEM_H__ */
 
index 2b58f0a1d67022d44c5a9ffc0bac76211822d332..2daf522954eb7a4de1c9e1c347e173754402f21b 100644 (file)
@@ -37,6 +37,7 @@
 
 typedef enum {
   MEMP_PBUF,
+  MEMP_RAW_PCB,
   MEMP_UDP_PCB,
   MEMP_TCP_PCB,
   MEMP_TCP_PCB_LISTEN,
index a0d1ad141a4fd0c7597066273a367b7c86b017ea..237bde450bad69a27f1903aef064249cf3ff905f 100644 (file)
@@ -32,9 +32,9 @@
 #ifndef __LWIP_OPT_H__
 #define __LWIP_OPT_H__
 
-#include "lwip/debug.h"
 /* Include user defined options first */
 #include "lwipopts.h"
+#include "lwip/debug.h"
 
 /* Define default values for unconfigured parameters. */
 
@@ -74,6 +74,11 @@ a lot of data that needs to be copied, this should be set high. */
 #define MEMP_NUM_PBUF                   16
 #endif
 
+/* Number of raw connection PCBs */
+#ifndef MEMP_NUM_RAW_PCB
+#define MEMP_NUM_RAW_PCB                4
+#endif
+
 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
    per active UDP "connection". */
 #ifndef MEMP_NUM_UDP_PCB
@@ -211,6 +216,12 @@ a lot of data that needs to be copied, this should be set high. */
 #define ICMP_TTL                        255
 #endif
 
+/* ---------- RAW options ---------- */
+
+#ifndef RAW_TTL
+#define RAW_TTL                        255
+#endif
+
 /* ---------- DHCP options ---------- */
 
 #ifndef LWIP_DHCP
@@ -320,6 +331,14 @@ a lot of data that needs to be copied, this should be set high. */
 #define DEFAULT_THREAD_PRIO             1
 #endif
 
+
+/* ---------- Socket Options ---------- */
+/* Enable SO_REUSEADDR and SO_REUSEPORT options */ 
+#ifndef SO_REUSE
+# define SO_REUSE 1
+#endif                                                                        
+
+
 /* ---------- Statistics options ---------- */
 #ifndef LWIP_STATS
 #define LWIP_STATS                      1
@@ -327,15 +346,63 @@ a lot of data that needs to be copied, this should be set high. */
 
 #if LWIP_STATS
 
-#define LINK_STATS
-#define IP_STATS
-#define ICMP_STATS
-#define UDP_STATS
-#define TCP_STATS
-#define MEM_STATS
-#define MEMP_STATS
-#define PBUF_STATS
-#define SYS_STATS
+#ifndef LINK_STATS
+#define LINK_STATS     1
+#endif
+
+#ifndef IP_STATS
+#define IP_STATS       1
+#endif
+
+#ifndef IPFRAG_STATS
+#define IPFRAG_STATS   1
+#endif
+
+#ifndef ICMP_STATS
+#define ICMP_STATS     1
+#endif
+
+#ifndef UDP_STATS
+#define UDP_STATS      1
+#endif
+
+#ifndef TCP_STATS
+#define TCP_STATS      1
+#endif
+
+#ifndef MEM_STATS
+#define MEM_STATS      1
+#endif
+
+#ifndef MEMP_STATS
+#define MEMP_STATS     1
+#endif
+
+#ifndef PBUF_STATS
+#define PBUF_STATS     1
+#endif
+
+#ifndef SYS_STATS
+#define SYS_STATS      1
+#endif
+
+#ifndef RAW_STATS
+#define RAW_STATS      0
+#endif
+
+#else
+
+#define LINK_STATS     0
+#define IP_STATS       0
+#define IPFRAG_STATS   0
+#define ICMP_STATS     0
+#define UDP_STATS      0
+#define TCP_STATS      0
+#define MEM_STATS      0
+#define MEMP_STATS     0
+#define PBUF_STATS     0
+#define SYS_STATS      0
+#define RAW_STATS      0
 
 #endif /* LWIP_STATS */
 
@@ -477,6 +544,10 @@ a lot of data that needs to be copied, this should be set high. */
 #define IP_REASS_DEBUG                  DBG_OFF
 #endif
 
+#ifndef RAW_DEBUG
+#define RAW_DEBUG                       DBG_OFF
+#endif
+
 #ifndef MEM_DEBUG
 #define MEM_DEBUG                       DBG_OFF
 #endif
index 3c755f7ef677ddf14832611df3ae126db56690ca..36c543195e607c2e9da10edd400fdc472ca99ed0 100644 (file)
@@ -29,7 +29,7 @@
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 #ifndef __LWIP_PBUF_H__
 #define __LWIP_PBUF_H__
 
@@ -108,6 +108,7 @@ void pbuf_ref(struct pbuf *p);
 void pbuf_ref_chain(struct pbuf *p);
 u8_t pbuf_free(struct pbuf *p);
 u8_t pbuf_clen(struct pbuf *p);  
+void pbuf_cat(struct pbuf *h, struct pbuf *t);
 void pbuf_chain(struct pbuf *h, struct pbuf *t);
 struct pbuf *pbuf_take(struct pbuf *f);
 struct pbuf *pbuf_dechain(struct pbuf *p);
diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h
new file mode 100644 (file)
index 0000000..acad136
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __LWIP_RAW_H__
+#define __LWIP_RAW_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/pbuf.h"
+#include "lwip/inet.h"
+#include "lwip/ip.h"
+
+struct raw_pcb {
+/* Common members of all PCB types */
+  IP_PCB;
+
+  struct raw_pcb *next;
+
+  u16_t protocol;
+
+  int (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+    struct ip_addr *addr);
+  void *recv_arg;
+};
+
+/* The following functions is the application layer interface to the
+   RAW code. */
+struct raw_pcb * raw_new        (u16_t proto);
+void             raw_remove     (struct raw_pcb *pcb);
+err_t            raw_bind       (struct raw_pcb *pcb, struct ip_addr *ipaddr);
+err_t            raw_connect    (struct raw_pcb *pcb, struct ip_addr *ipaddr);
+
+void             raw_recv       (struct raw_pcb *pcb,
+                                 int (* recv)(void *arg, struct raw_pcb *pcb,
+                                              struct pbuf *p,
+                                              struct ip_addr *addr),
+                                 void *recv_arg);
+err_t            raw_send_to    (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
+err_t            raw_send       (struct raw_pcb *pcb, struct pbuf *p);
+
+/* The following functions are the lower layer interface to RAW. */
+int              raw_input      (struct pbuf *p, struct netif *inp);
+void             raw_init       (void);
+
+
+#endif /* __LWIP_RAW_H__ */
index d460d84fb4b4526fb2689f675451140346552d20..2bf7740e3bf7f04c635edfed0680b2b04a83403b 100644 (file)
@@ -70,6 +70,7 @@ struct sockaddr {
 #define  SO_USELOOPBACK  0x0040    /* bypass hardware when possible */
 #define  SO_LINGER  0x0080    /* linger on close if data present */
 #define  SO_OOBINLINE  0x0100    /* leave received OOB data in line */
+#define         SO_REUSEPORT   0x0200          /* allow local address & port reuse */
 
 #define SO_DONTLINGER   (int)(~SO_LINGER)
 
@@ -117,6 +118,36 @@ struct linger {
 #define MSG_DONTWAIT    0x40            /* Nonblocking i/o for this operation only */
 
 
+/*
+ * Options for level IPPROTO_IP
+ */
+#define IP_TOS       1
+#define IP_TTL       2
+
+
+#define IPTOS_TOS_MASK          0x1E
+#define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
+#define IPTOS_LOWDELAY          0x10
+#define IPTOS_THROUGHPUT        0x08
+#define IPTOS_RELIABILITY       0x04
+#define IPTOS_LOWCOST           0x02
+#define IPTOS_MINCOST           IPTOS_LOWCOST
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define IPTOS_PREC_MASK                 0xe0
+#define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
+#define IPTOS_PREC_NETCONTROL           0xe0
+#define IPTOS_PREC_INTERNETCONTROL      0xc0
+#define IPTOS_PREC_CRITIC_ECP           0xa0
+#define IPTOS_PREC_FLASHOVERRIDE        0x80
+#define IPTOS_PREC_FLASH                0x60
+#define IPTOS_PREC_IMMEDIATE            0x40
+#define IPTOS_PREC_PRIORITY             0x20
+#define IPTOS_PREC_ROUTINE              0x00
+
+
 /*
  * Commands for ioctlsocket(),  taken from the BSD file fcntl.h.
  *
index 3ccc3e757459417cf1bb7115e62ba159abec9e8c..ac06a6d3e5a5d7aedf5478f19d23ca7b801b1492 100644 (file)
@@ -101,9 +101,49 @@ extern struct stats_ lwip_stats;
 
 
 void stats_init(void);
+
+#define STATS_INC(x) ++lwip_stats.x
 #else
 #define stats_init()
+#define STATS_INC(x)
 #endif /* LWIP_STATS */
+
+#if TCP_STATS
+#define TCP_STATS_INC(x) STATS_INC(x)
+#else
+#define TCP_STATS_INC(x)
+#endif
+
+#if UDP_STATS
+#define UDP_STATS_INC(x) STATS_INC(x)
+#else
+#define UDP_STATS_INC(x)
+#endif
+
+#if ICMP_STATS
+#define ICMP_STATS_INC(x) STATS_INC(x)
+#else
+#define ICMP_STATS_INC(x)
+#endif
+
+#if IP_STATS
+#define IP_STATS_INC(x) STATS_INC(x)
+#else
+#define IP_STATS_INC(x)
+#endif
+
+#if IPFRAG_STATS
+#define IPFRAG_STATS_INC(x) STATS_INC(x)
+#else
+#define IPFRAG_STATS_INC(x)
+#endif
+
+#if LINK_STATS
+#define LINK_STATS_INC(x) STATS_INC(x)
+#else
+#define LINK_STATS_INC(x)
+#endif
+
 #endif /* __LWIP_STATS_H__ */
 
 
index 72f2593c559c9795d9e920d070f7ac0b7ed09183..1231f6e77747bb6a44a3ad73cd9c6284eaa37193 100644 (file)
@@ -53,7 +53,7 @@ void             tcp_init    (void);  /* Must be called first to
            initialize TCP. */
 void             tcp_tmr     (void);  /* Must be called every
            TCP_TMR_INTERVAL
-           ms. (Typically 100 ms). */
+           ms. (Typically 250 ms). */
 /* Application program's interface: */
 struct tcp_pcb * tcp_new     (void);
 struct tcp_pcb * tcp_alloc   (u8_t prio);
@@ -115,30 +115,32 @@ void             tcp_rexmit  (struct tcp_pcb *pcb);
 #define TCP_SEQ_GT(a,b)     ((s32_t)((a)-(b)) > 0)
 #define TCP_SEQ_GEQ(a,b)    ((s32_t)((a)-(b)) >= 0)
 
-#define TCP_FIN 0x01
-#define TCP_SYN 0x02
-#define TCP_RST 0x04
-#define TCP_PSH 0x08
-#define TCP_ACK 0x10
-#define TCP_URG 0x20
+#define TCP_FIN 0x01U
+#define TCP_SYN 0x02U
+#define TCP_RST 0x04U
+#define TCP_PSH 0x08U
+#define TCP_ACK 0x10U
+#define TCP_URG 0x20U
+#define TCP_ECE 0x40U
+#define TCP_CWR 0x80U
 
-#define TCP_FLAGS 0x3f
+#define TCP_FLAGS 0x3fU
 
 /* Length of the TCP header, excluding options. */
 #define TCP_HLEN 20
 
 #ifndef TCP_TMR_INTERVAL
-#define TCP_TMR_INTERVAL       100  /* The TCP timer interval in
+#define TCP_TMR_INTERVAL       250  /* The TCP timer interval in
                                        milliseconds. */
 #endif /* TCP_TMR_INTERVAL */
 
 #ifndef TCP_FAST_INTERVAL
-#define TCP_FAST_INTERVAL      200  /* the fine grained timeout in
+#define TCP_FAST_INTERVAL      TCP_TMR_INTERVAL /* the fine grained timeout in
                                        milliseconds */
 #endif /* TCP_FAST_INTERVAL */
 
 #ifndef TCP_SLOW_INTERVAL
-#define TCP_SLOW_INTERVAL      500  /* the coarse grained timeout in
+#define TCP_SLOW_INTERVAL      (2*TCP_TMR_INTERVAL)  /* the coarse grained timeout in
                                        milliseconds */
 #endif /* TCP_SLOW_INTERVAL */
 
@@ -149,6 +151,19 @@ void             tcp_rexmit  (struct tcp_pcb *pcb);
 
 #define TCP_MSL 60000  /* The maximum segment lifetime in microseconds */
 
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define        TCP_NODELAY        0x01    /* don't delay send to coalesce packets */
+#define TCP_KEEPALIVE  0x02    /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
+
+/* Keepalive values */
+#define  TCP_KEEPDEFAULT   7200000                       /* KEEPALIVE timer in miliseconds */
+#define  TCP_KEEPINTVL     75000                         /* Time between KEEPALIVE probes in miliseconds */
+#define  TCP_KEEPCNT       9                             /* Counter for KEEPALIVE probes */
+#define  TCP_MAXIDLE       TCP_KEEPCNT * TCP_KEEPINTVL   /* Maximum KEEPALIVE probe time */
+
+
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
 #endif
@@ -158,7 +173,7 @@ struct tcp_hdr {
   PACK_STRUCT_FIELD(u16_t dest);
   PACK_STRUCT_FIELD(u32_t seqno);
   PACK_STRUCT_FIELD(u32_t ackno);
-  PACK_STRUCT_FIELD(u16_t _offset_flags);
+  PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
   PACK_STRUCT_FIELD(u16_t wnd);
   PACK_STRUCT_FIELD(u16_t chksum);
   PACK_STRUCT_FIELD(u16_t urgp);
@@ -168,11 +183,15 @@ PACK_STRUCT_END
 #  include "arch/epstruct.h"
 #endif
 
-#define TCPH_OFFSET(hdr) (ntohs((hdr)->_offset_flags) >> 8)
-#define TCPH_FLAGS(hdr) (ntohs((hdr)->_offset_flags) & 0xff)
+#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
+#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
+#define TCPH_FLAGS(phdr)  (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
 
-#define TCPH_OFFSET_SET(hdr, offset) (hdr)->_offset_flags = htons(((offset) << 8) | TCPH_FLAGS(hdr))
-#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = htons((TCPH_OFFSET(hdr) << 8) | (flags))
+#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
+#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
+#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
+#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
 
 #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
           TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
@@ -194,17 +213,30 @@ enum tcp_state {
 
 /* the TCP protocol control block */
 struct tcp_pcb {
+/* Common members of all PCB types */
+  IP_PCB;
+
+/* Protocol specific PCB members */
+
   struct tcp_pcb *next;   /* for the linked list */
+
+  enum tcp_state state;   /* TCP state */
+
   u8_t prio;
   void *callback_arg;
 
-  struct ip_addr local_ip;
   u16_t local_port;
-  enum tcp_state state;   /* TCP state */
-  
-  struct ip_addr remote_ip;
   u16_t remote_port;
   
+  u8_t flags;
+#define TF_ACK_DELAY (u8_t)0x01U   /* Delayed ACK. */
+#define TF_ACK_NOW   (u8_t)0x02U   /* Immediate ACK. */
+#define TF_INFR      (u8_t)0x04U   /* In fast recovery. */
+#define TF_RESET     (u8_t)0x08U   /* Connection was reset. */
+#define TF_CLOSED    (u8_t)0x10U   /* Connection was sucessfully closed. */
+#define TF_GOT_FIN   (u8_t)0x20U   /* Connection was closed by the remote end. */
+#define TF_NODELAY   (u8_t)0x40U   /* Disable Nagle algorithm */
+
   /* receiver varables */
   u32_t rcv_nxt;   /* next seqno expected */
   u16_t rcv_wnd;   /* receiver window */
@@ -217,14 +249,6 @@ struct tcp_pcb {
   u16_t rtime;
   
   u16_t mss;   /* maximum segment size */
-
-  u8_t flags;
-#define TF_ACK_DELAY 0x01U   /* Delayed ACK. */
-#define TF_ACK_NOW   0x02U   /* Immediate ACK. */
-#define TF_INFR      0x04U   /* In fast recovery. */
-#define TF_RESET     0x08U   /* Connection was reset. */
-#define TF_CLOSED    0x10U   /* Connection was sucessfully closed. */
-#define TF_GOT_FIN   0x20U   /* Connection was closed by the remote end. */
   
   /* RTT estimation variables. */
   u16_t rttest; /* RTT estimate in 500ms ticks */
@@ -282,21 +306,32 @@ struct tcp_pcb {
   /* Function to be called whenever a fatal error occurs. */
   void (* errf)(void *arg, err_t err);
 #endif /* LWIP_CALLBACK_API */
+
+  /* idle time before KEEPALIVE is sent */
+  u32_t keepalive;
+  
+  /* KEEPALIVE counter */
+  u8_t keep_cnt;
 };
 
 struct tcp_pcb_listen {  
+/* Common members of all PCB types */
+  IP_PCB;
+
+/* Protocol specific PCB members */
   struct tcp_pcb_listen *next;   /* for the linked list */
-  u8_t prio;
-  void *callback_arg;
   
-  struct ip_addr local_ip;
-  u16_t local_port; 
   /* Even if state is obviously LISTEN this is here for
    * field compatibility with tpc_pcb to which it is cast sometimes
    * Until a cleaner solution emerges this is here.FIXME
    */ 
   enum tcp_state state;   /* TCP state */
 
+  u8_t prio;
+  void *callback_arg;
+  
+  u16_t local_port; 
+
 #if LWIP_CALLBACK_API
   /* Function to call when a listener has been connected. */
   err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
@@ -396,6 +431,8 @@ void tcp_rst(u32_t seqno, u32_t ackno,
 
 u32_t tcp_next_iss(void);
 
+void tcp_keepalive(struct tcp_pcb *pcb);
+
 extern struct tcp_pcb *tcp_input_pcb;
 extern u32_t tcp_ticks;
 
@@ -406,7 +443,11 @@ void tcp_debug_print_state(enum tcp_state s);
 void tcp_debug_print_pcbs(void);
 int tcp_pcbs_sane(void);
 #else
-#define tcp_pcbs_sane() 1
+#  define tcp_debug_print(tcphdr)
+#  define tcp_debug_print_flags(flags)
+#  define tcp_debug_print_state(s)
+#  define tcp_debug_print_pcbs()
+#  define tcp_pcbs_sane() 1
 #endif /* TCP_DEBUG */
 
 #if NO_SYS
index 84d2bfdef2d2c1c74dfb16eba46cef30ee610558..00ac4f0b7ea67583ee5e2d26cd02f17d168aca74 100644 (file)
@@ -52,12 +52,16 @@ struct udp_hdr {
 #define UDP_FLAGS_CONNECTED  0x04U
 
 struct udp_pcb {
+/* Common members of all PCB types */
+  IP_PCB;
+
+/* Protocol specific PCB members */
+
   struct udp_pcb *next;
 
-  struct ip_addr local_ip, remote_ip;
+  u8_t flags;
   u16_t local_port, remote_port;
   
-  u8_t flags;
   u16_t chksum_len;
   
   void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@@ -91,7 +95,11 @@ u8_t             udp_lookup     (struct ip_hdr *iphdr, struct netif *inp);
 void             udp_input      (struct pbuf *p, struct netif *inp);
 void             udp_init       (void);
 
-
+#if UDP_DEBUG
+int udp_debug_print(struct udp_hdr *udphdr);
+#else
+#define udp_debug_print(udphdr)
+#endif
 #endif /* __LWIP_UDP_H__ */
 
 
index 1b5607ca5a406e3548e8dc8ffef2d758039122a3..fa6e917fc1979d1f94ab289bd792b6dcb9c47c41 100644 (file)
@@ -4,8 +4,10 @@
  *
  * Functionally, ARP is divided into two parts. The first maps an IP address
  * to a physical address when sending a packet, and the second part answers
- * requests from other machines.
+ * requests from other machines for our physical address.
  *
+ * This implementation complies with RFC 826 (Ethernet ARP) and supports
+ * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6.
  */
 
 /*
@@ -156,23 +158,16 @@ etharp_tmr(void)
     if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
         (arp_table[i].ctime >= ARP_MAXAGE)) {
       LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
-      arp_table[i].state = ETHARP_STATE_EMPTY;
-#if ARP_QUEUEING
-      if (arp_table[i].p != NULL) {
-        /* remove any queued packet */
-        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
-        pbuf_free(arp_table[i].p);
-        arp_table[i].p = NULL;
-      }
-#endif
+      goto empty;
     } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
         (arp_table[i].ctime >= ARP_MAXPENDING)) {
-      arp_table[i].state = ETHARP_STATE_EMPTY;
       LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
+  empty:      
+      arp_table[i].state = ETHARP_STATE_EMPTY;
 #if ARP_QUEUEING
       if (arp_table[i].p != NULL) {
         /* remove any queued packet */
-        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
+        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
         pbuf_free(arp_table[i].p);
         arp_table[i].p = NULL;
       }
@@ -292,6 +287,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
           ethhdr = p->payload;
           for (k = 0; k < netif->hwaddr_len; ++k) {
             ethhdr->dest.addr[k] = ethaddr->addr[k];
+            ethhdr->src.addr[k] = netif->hwaddr[k];
           }
           ethhdr->type = htons(ETHTYPE_IP);
           LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));
@@ -390,7 +386,8 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
 
 
 /**
- * Responds to ARP requests, updates ARP entries and sends queued IP packets.
+ * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache  
+ * send out queued IP packets. Updates cache with snooped address pairs.
  *
  * Should be called for incoming ARP packets. The pbuf in the argument
  * is freed by this function.
@@ -408,15 +405,24 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
 {
   struct etharp_hdr *hdr;
   u8_t i;
+  u8_t for_us;
 
   /* drop short ARP packets */
   if (p->tot_len < sizeof(struct etharp_hdr)) {
-    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
+    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
     pbuf_free(p);
     return NULL;
   }
 
   hdr = p->payload;
+  /* this interface is not configured? */
+  if (netif->ip_addr.addr == 0) {
+    for_us = 0;
+  } else {
+    /* ARP packet directed to us? */
+    for_us = ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr));
+  }
 
   switch (htons(hdr->opcode)) {
   /* ARP request? */
@@ -432,10 +438,8 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
       pbuf_free(p);
       return NULL;
     }
-    /* update the ARP cache */
-    update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
     /* ARP request for our address? */
-    if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
+    if (for_us) {
 
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
       /* re-use pbuf to send ARP reply */
@@ -454,41 +458,42 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
       hdr->hwtype = htons(HWTYPE_ETHERNET);
       ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
 
-        hdr->proto = htons(ETHTYPE_IP);
+      hdr->proto = htons(ETHTYPE_IP);
       ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
 
-        hdr->ethhdr.type = htons(ETHTYPE_ARP);
+      hdr->ethhdr.type = htons(ETHTYPE_ARP);
       /* return ARP reply */
       netif->linkoutput(netif, p);
+
+    /* request was not directed to us */
     } else {
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
     }
     break;
   case ARP_REPLY:
-    /* ARP reply. We insert or update the ARP table. */
+    /* ARP reply. We insert or update the ARP table later. */
     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
-    /* DHCP needs to know about ARP replies */
-    dhcp_arp_reply(netif, &hdr->sipaddr);
+    /* DHCP needs to know about ARP replies to our address */
+    if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr);
 #endif
-    /* ARP reply directed to us? */
-    if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
-      LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n"));
-      /* update_the ARP cache, ask to insert */
-      update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
-    /* ARP reply not directed to us */
-    } else {
-      LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n"));
-      /* update the destination address pair */
-      update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
-      /* update the destination address pair */
-      update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
-    }
     break;
   default:
     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
     break;
   }
+  /* add or update entries in the ARP cache */
+  if (for_us) {
+    /* insert IP address in ARP cache (assume requester wants to talk to us)
+     * we might even send out a queued packet to this host */
+    update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
+  /* request was not directed to us, but snoop anyway */
+  } else {
+    /* update or insert the source IP address in the cache */
+    update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
+    /* update or insert the destination IP address pair in the cache */
+    update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
+  }
   /* free ARP packet */
   pbuf_free(p);
   p = NULL;
@@ -503,9 +508,9 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
  * returned, ready to be sent.
  *
  * If ARP does not have the Ethernet address in cache the packet is
- * queued and a ARP request is sent (on a best-effort basis). This
- * ARP request is returned as a pbuf, which should be sent by the
- * caller.
+ * queued (if enabled and space available) and a ARP request is sent.
+ * This ARP request is returned as a pbuf, which should be sent by
+ * the caller.
  *
  * If ARP failed to allocate resources, NULL is returned.
  *
@@ -515,7 +520,8 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
  * @param ipaddr The IP address of the packet destination.
  * @param pbuf The pbuf(s) containing the IP packet to be sent.
  *
- * @return If non-NULL, a packet ready to be sent.
+ * @return If non-NULL, a packet ready to be sent by caller.
+ *
  */
 struct pbuf *
 etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
@@ -529,9 +535,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
     /* The pbuf_header() call shouldn't fail, and we'll just bail
     out if it does.. */
     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
-#ifdef LINK_STATS
-    ++lwip_stats.link.lenerr;
-#endif /* LINK_STATS */
+    LINK_STATS_INC(link.lenerr);
     return NULL;
   }
 
@@ -541,9 +545,9 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
   /* assume unresolved Ethernet address */
   dest = NULL;
   /* Construct Ethernet header. Start with looking up deciding which
-  MAC address to use as a destination address. Broadcasts and
-  multicasts are special, all other addresses are looked up in the
-  ARP table. */
+     MAC address to use as a destination address. Broadcasts and
+     multicasts are special, all other addresses are looked up in the
+     ARP table. */
 
   /* destination IP address is an IP broadcast address? */
   if (ip_addr_isany(ipaddr) ||
@@ -555,7 +559,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
   else if (ip_addr_ismulticast(ipaddr)) {
     /* Hash IP multicast address to MAC address. */
     mcastaddr.addr[0] = 0x01;
-    mcastaddr.addr[1] = 0x0;
+    mcastaddr.addr[1] = 0x00;
     mcastaddr.addr[2] = 0x5e;
     mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
     mcastaddr.addr[4] = ip4_addr3(ipaddr);
@@ -583,7 +587,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
     }
 
     /* Ethernet address for IP destination address is in ARP cache? */
-    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+    for (i = 0; i < ARP_TABLE_SIZE; ++i) {
       /* match found? */
       if (arp_table[i].state == ETHARP_STATE_STABLE &&
         ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
@@ -594,6 +598,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
     /* could not find the destination Ethernet address in ARP cache? */
     if (dest == NULL) {
       /* ARP query for the IP address, submit this IP packet for queueing */
+      /* TODO: How do we handle netif->ipaddr == ipaddr? */
       etharp_query(netif, ipaddr, q);
       /* return nothing */
       return NULL;
@@ -736,10 +741,12 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
       hdr = p->payload;
       hdr->opcode = htons(ARP_REQUEST);
-      for(j = 0; j < netif->hwaddr_len; ++j)
+      for (j = 0; j < netif->hwaddr_len; ++j)
       {
-        hdr->dhwaddr.addr[j] = 0x00;
         hdr->shwaddr.addr[j] = srcaddr->addr[j];
+        /* the hardware address is what we ask for, in
+         * a request it is a don't-care, we use 0's */
+        hdr->dhwaddr.addr[j] = 0x00;
       }
       ip_addr_set(&(hdr->dipaddr), ipaddr);
       ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
@@ -749,7 +756,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
 
       hdr->proto = htons(ETHTYPE_IP);
       ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
-      for(j = 0; j < netif->hwaddr_len; ++j)
+      for (j = 0; j < netif->hwaddr_len; ++j)
       {
         hdr->ethhdr.dest.addr[j] = 0xff;
         hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
index efecfe17cf9dbeac11fb3b2054749b53d89ed972..557c00c6fe6ce967b276317adac0397300bcae93 100644 (file)
@@ -63,7 +63,7 @@ static void  ethernetif_input(struct netif *netif);
 static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
              struct ip_addr *ipaddr);
 
-/*-----------------------------------------------------------------------------------*/
+
 static void
 low_level_init(struct netif *netif)
 {
@@ -87,7 +87,7 @@ low_level_init(struct netif *netif)
  
   /* Do whatever else is needed to initialize interface. */  
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * low_level_output():
  *
@@ -96,7 +96,7 @@ low_level_init(struct netif *netif)
  * might be chained.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 
 static err_t
 low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
@@ -120,7 +120,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
 
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * low_level_input():
  *
@@ -128,7 +128,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
  * packet from the interface into the pbuf.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 static struct pbuf *
 low_level_input(struct ethernetif *ethernetif)
 {
@@ -165,7 +165,7 @@ low_level_input(struct ethernetif *ethernetif)
 
   return p;  
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * ethernetif_output():
  *
@@ -174,7 +174,7 @@ low_level_input(struct ethernetif *ethernetif)
  * do the actuall transmission of the packet.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 static err_t
 ethernetif_output(struct netif *netif, struct pbuf *p,
       struct ip_addr *ipaddr)
@@ -264,7 +264,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
   return low_level_output(ethernetif, p);
 
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * ethernetif_input():
  *
@@ -274,7 +274,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
  * interface.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 static void
 ethernetif_input(struct netif *netif)
 {
@@ -314,14 +314,14 @@ ethernetif_input(struct netif *netif)
     }
   }
 }
-/*-----------------------------------------------------------------------------------*/
+
 static void
 arp_timer(void *arg)
 {
   arp_tmr();
   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
 /*
  * ethernetif_init():
  *
@@ -330,7 +330,7 @@ arp_timer(void *arg)
  * actual setup of the hardware.
  *
  */
-/*-----------------------------------------------------------------------------------*/
+
 void
 ethernetif_init(struct netif *netif)
 {
@@ -350,4 +350,4 @@ ethernetif_init(struct netif *netif)
 
   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
 }
-/*-----------------------------------------------------------------------------------*/
+
index c6f10e3871a96bc907bf43b249536e39298290bf..1a8e2e283a598b610f13fd3d68ab2524ab65af08 100644 (file)
 #include "lwip/tcp.h"
 #include "lwip/ip.h"
 
-/*-----------------------------------------------------------------------------------*/
+static void
+loopif_input( void * arg )
+{
+       struct netif *netif = (struct netif *)( ((void **)arg)[ 0 ] );
+       struct pbuf *r = (struct pbuf *)( ((void **)arg)[ 1 ] );
+
+       mem_free( arg );
+       netif -> input( r, netif );
+}
+
 static err_t
 loopif_output(struct netif *netif, struct pbuf *p,
        struct ip_addr *ipaddr)
 {
   struct pbuf *q, *r;
   char *ptr;
+  void **arg;
 
 #if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
   tcpdump(p);
@@ -60,21 +70,42 @@ loopif_output(struct netif *netif, struct pbuf *p,
       memcpy(ptr, q->payload, q->len);
       ptr += q->len;
     }
-    netif->input(r, netif);
+
+    arg = mem_malloc( sizeof( void *[2]));
+       if( NULL == arg ) {
+               return ERR_MEM;
+       }
+       
+       arg[0] = netif;
+       arg[1] = r;
+       /**
+        * workaround (patch #1779) to try to prevent bug #2595:
+        * When connecting to "localhost" with the loopif interface,
+        * tcp_output doesn't get the opportunity to finnish sending the
+        * segment before tcp_process gets it, resulting in tcp_process
+        * referencing pcb->unacked-> which still is NULL.
+        * 
+        * TODO: Is there still a race condition here? Leon
+        */
+       sys_timeout( 1, loopif_input, arg );
+       
     return ERR_OK;    
   }
   return ERR_MEM;
 }
-/*-----------------------------------------------------------------------------------*/
+
 err_t
 loopif_init(struct netif *netif)
 {
   netif->name[0] = 'l';
   netif->name[1] = 'o';
+#if 0 /** TODO: I think this should be enabled, or not? Leon */
+  netif->input = loopif_input;
+#endif
   netif->output = loopif_output;
   return ERR_OK;
 }
-/*-----------------------------------------------------------------------------------*/
+
 
 
 
index f7c797600dc13fca1b923e6e2c76950dd3cf0e68..45001336aa33972bcae6b44df14e92a28697fbe7 100644 (file)
@@ -194,7 +194,7 @@ void link_terminated(int unit)
     if (logged_in)
         logout();
     lcp_phase[unit] = PHASE_DEAD;
-    ppp_trace(LOG_NOTICE, "Connection terminated.\n");
+    AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
        pppMainWakeup(unit);
 }
 
@@ -257,7 +257,7 @@ void link_established(int unit)
          * of "" and a password of "".  If that's not OK, boot it out.
          */
         if (!wo->neg_upap || !null_login(unit)) {
-            ppp_trace(LOG_WARNING, "peer refused to authenticate\n");
+            AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
             lcp_close(unit, "peer refused to authenticate");
             return;
         }
@@ -294,7 +294,7 @@ void link_established(int unit)
         if (ppp_settings.passwd[0] == 0) {
             passwd_from_file = 1;
             if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd))
-                ppp_trace(LOG_ERR, "No secret found for PAP login\n");
+                AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
         }
         upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
         auth |= PAP_WITHPEER;
@@ -337,8 +337,8 @@ void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
         pbit = PAP_PEER;
         break;
     default:
-        ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
-               protocol);
+        AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
+               protocol));
         return;
     }
     
@@ -400,8 +400,8 @@ void auth_withpeer_success(int unit, u16_t protocol)
         pbit = PAP_WITHPEER;
         break;
     default:
-        ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
-               protocol);
+        AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
+               protocol));
         pbit = 0;
     }
     
@@ -541,7 +541,7 @@ int check_passwd(
          * On 10'th, drop the connection.
          */
         if (attempts++ >= 10) {
-            ppp_trace(LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user);
+            AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
             /*ppp_panic("Excess Bad Logins");*/
         }
         if (attempts > 3) {
@@ -616,7 +616,7 @@ int get_secret(
 
     len = strlen(ppp_settings.passwd);
     if (len > MAXSECRETLEN) {
-        ppp_trace(LOG_ERR, "Secret for %s on %s is too long\n", client, server);
+        AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
         len = MAXSECRETLEN;
     }
     BCOPY(ppp_settings.passwd, secret, len);
@@ -640,7 +640,7 @@ int get_secret(
     
     len = strlen(secbuf);
     if (len > MAXSECRETLEN) {
-        ppp_trace(LOG_ERR, "Secret for %s on %s is too long\n", client, server);
+        AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
         len = MAXSECRETLEN;
     }
     BCOPY(secbuf, secret, len);
@@ -753,7 +753,7 @@ static void check_idle(void *arg)
     itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
     if (itime >= ppp_settings.idle_time_limit) {
         /* link is idle: shut it down. */
-        ppp_trace(LOG_INFO, "Terminating connection due to lack of activity.\n");
+        AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));
         lcp_close(0, "Link inactive");
     } else {
         TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
@@ -767,7 +767,7 @@ static void connect_time_expired(void *arg)
 {
        (void)arg;
 
-    ppp_trace(LOG_INFO, "Connect time expired\n");
+    AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
     lcp_close(0, "Connect time expired");   /* Close connection */
 }
 
index 1e07aaf8198056b85608f110fa4993c6d73e54df..d94e54ee7d73638c248ee2c59ec745d868c20e35 100644 (file)
@@ -307,7 +307,7 @@ void pppInit(void)
             (*protp->init)(i);
     }
 
-#ifdef LINK_STATS
+#if LINK_STATS
     /* Clear the statistics. */
     memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
 #endif
@@ -326,6 +326,29 @@ void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
 #endif
            ppp_settings.refuse_chap = 1;
            break;
+       case PPPAUTHTYPE_ANY:
+/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
+ * RFC 1994 says:
+ *
+ * In practice, within or associated with each PPP server, there is a
+ * database which associates "user" names with authentication
+ * information ("secrets").  It is not anticipated that a particular
+ * named user would be authenticated by multiple methods.  This would
+ * make the user vulnerable to attacks which negotiate the least secure
+ * method from among a set (such as PAP rather than CHAP).  If the same
+ * secret was used, PAP would reveal the secret to be used later with
+ * CHAP.
+ *
+ * Instead, for each user name there should be an indication of exactly
+ * one method used to authenticate that user name.  If a user needs to
+ * make use of different authentication methods under different
+ * circumstances, then distinct user names SHOULD be employed, each of
+ * which identifies exactly one authentication method.
+ *
+ */
+           ppp_settings.refuse_pap = 0;
+           ppp_settings.refuse_chap = 0;
+           break;
        case PPPAUTHTYPE_PAP:
            ppp_settings.refuse_pap = 0;
            ppp_settings.refuse_chap = 1;
@@ -459,7 +482,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
            if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
                PPPDEBUG((LOG_WARNING,
                            "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.err++;
 #endif /* LINK_STATS */
                pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
@@ -468,7 +491,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
        }
        pbuf_free(nb);
 
-#ifdef LINK_STATS
+#if LINK_STATS
        lwip_stats.link.xmit++;
 #endif /* LINK_STATS */
 }
@@ -492,7 +515,7 @@ static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
        if (tb) {
            nb->next = tb;
         }
-#ifdef LINK_STATS
+#if LINK_STATS
        else {
            lwip_stats.link.memerr++;
        }
@@ -529,7 +552,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
        if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
         PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
                     pd, protocol, pb));
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.opterr++;
                lwip_stats.link.drop++;
 #endif
@@ -539,7 +562,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
     /* Check that the link is up. */
        if (lcp_phase[pd] == PHASE_DEAD) {
         PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.rterr++;
                lwip_stats.link.drop++;
 #endif
@@ -550,7 +573,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
        headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
     if (headMB == NULL) {
         PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.memerr++;
                lwip_stats.link.drop++;
 #endif /* LINK_STATS */
@@ -577,7 +600,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
             break;
         default:
             PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
-#ifdef LINK_STATS
+#if LINK_STATS
                        lwip_stats.link.proterr++;
                        lwip_stats.link.drop++;
 #endif
@@ -639,7 +662,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
                     "pppifOutput[%d]: Alloc err - dropping proto=%d\n", 
                     pd, protocol));
         pbuf_free(headMB);
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.memerr++;
                lwip_stats.link.drop++;
 #endif
@@ -728,7 +751,7 @@ int pppWrite(int pd, const u_char *s, int n)
     struct pbuf *headMB = NULL, *tailMB;
        headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
     if (headMB == NULL) {
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.memerr++;
                lwip_stats.link.proterr++;
 #endif /* LINK_STATS */
@@ -768,7 +791,7 @@ int pppWrite(int pd, const u_char *s, int n)
                 "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
 /*                "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
                pbuf_free(headMB);
-#ifdef LINK_STATS
+#if LINK_STATS
                lwip_stats.link.memerr++;
                lwip_stats.link.proterr++;
 #endif /* LINK_STATS */
@@ -1275,7 +1298,7 @@ static void pppInput(void *arg)
 
     pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
 
-#ifdef LINK_STATS
+#if LINK_STATS
     lwip_stats.link.recv++;
 #endif /* LINK_STATS */
 
@@ -1365,7 +1388,7 @@ static void pppInput(void *arg)
     }
 
 drop:
-#ifdef LINK_STATS
+#if LINK_STATS
     lwip_stats.link.drop++;
 #endif
 
@@ -1395,7 +1418,7 @@ static void pppDrop(PPPControl *pc)
     vj_uncompress_err(&pc->vjComp);
 #endif
 
-#ifdef LINK_STATS
+#if LINK_STATS
     lwip_stats.link.drop++;
 #endif /* LINK_STATS */
 }
@@ -1433,7 +1456,7 @@ static void pppInProc(int pd, u_char *s, int l)
                     PPPDEBUG((LOG_WARNING,
                                 "pppInProc[%d]: Dropping incomplete packet %d\n", 
                                 pd, pc->inState));
-#ifdef LINK_STATS
+#if LINK_STATS
                                        lwip_stats.link.lenerr++;
 #endif
                     pppDrop(pc);
@@ -1443,7 +1466,7 @@ static void pppInProc(int pd, u_char *s, int l)
                     PPPDEBUG((LOG_INFO,
                                 "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n", 
                                 pd, pc->inFCS, pc->inProtocol));
-#ifdef LINK_STATS
+#if LINK_STATS
                                        lwip_stats.link.chkerr++;
 #endif
                     pppDrop(pc);
@@ -1457,14 +1480,12 @@ static void pppInProc(int pd, u_char *s, int l)
 
                        pc->inTail->tot_len = pc->inTail->len;
                        if (pc->inTail != pc->inHead) {
-                           pbuf_chain(pc->inHead, pc->inTail);
-                           pbuf_free(pc->inTail);
+                           pbuf_cat(pc->inHead, pc->inTail);
                        }
                    } else {
                        pc->inTail->tot_len = pc->inTail->len;
                        if (pc->inTail != pc->inHead) {
-                           pbuf_chain(pc->inHead, pc->inTail);
-                           pbuf_free(pc->inTail);
+                           pbuf_cat(pc->inHead, pc->inTail);
                        }
 
                        pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
@@ -1475,7 +1496,7 @@ static void pppInProc(int pd, u_char *s, int l)
                        PPPDEBUG((LOG_ERR,
                                    "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
                        pbuf_free(pc->inHead);
-#ifdef LINK_STATS
+#if LINK_STATS
                        lwip_stats.link.drop++;
 #endif
                    }
@@ -1560,8 +1581,7 @@ static void pppInProc(int pd, u_char *s, int l)
                    if(pc->inTail) {
                        pc->inTail->tot_len = pc->inTail->len;
                        if (pc->inTail != pc->inHead) {
-                           pbuf_chain(pc->inHead, pc->inTail);
-                           pbuf_free(pc->inTail);
+                           pbuf_cat(pc->inHead, pc->inTail);
                        }
                    }
                     /* If we haven't started a packet, we need a packet header. */
@@ -1571,7 +1591,7 @@ static void pppInProc(int pd, u_char *s, int l)
                          * higher layers deal with it.  Continue processing
                          * the received pbuf chain in case a new packet starts. */
                         PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
-#ifdef LINK_STATS
+#if LINK_STATS
                                                lwip_stats.link.memerr++;
 #endif /* LINK_STATS */
                         pppDrop(pc);
index d4d140755768fbdc574bcb551acf7e0d0e7c5224..dbe12171e83beca26818af78a2bd526975a0888a 100644 (file)
@@ -208,8 +208,11 @@ enum NPmode {
 #define BCMP(s0, s1, l)     memcmp((u_char *)(s0), (u_char *)(s1), (l))
 #define BCOPY(s, d, l)      memcpy((d), (s), (l))
 #define BZERO(s, n)         memset(s, 0, n)
-
+#if PPP_DEBUG
 #define PRINTMSG(m, l)  { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
+#else
+#define PRINTMSG(m, l)
+#endif
 
 /*
  * MAKEHEADER - Add PPP Header fields to a packet.
@@ -340,8 +343,28 @@ extern struct protent *ppp_protocols[];/* Table of pointers to supported protoco
 /* Initialize the PPP subsystem. */
 void pppInit(void);
 
+/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
+ * RFC 1994 says:
+ *
+ * In practice, within or associated with each PPP server, there is a
+ * database which associates "user" names with authentication
+ * information ("secrets").  It is not anticipated that a particular
+ * named user would be authenticated by multiple methods.  This would
+ * make the user vulnerable to attacks which negotiate the least secure
+ * method from among a set (such as PAP rather than CHAP).  If the same
+ * secret was used, PAP would reveal the secret to be used later with
+ * CHAP.
+ *
+ * Instead, for each user name there should be an indication of exactly
+ * one method used to authenticate that user name.  If a user needs to
+ * make use of different authentication methods under different
+ * circumstances, then distinct user names SHOULD be employed, each of
+ * which identifies exactly one authentication method.
+ *
+ */
 enum pppAuthType {
     PPPAUTHTYPE_NONE,
+    PPPAUTHTYPE_ANY,
     PPPAUTHTYPE_PAP,
     PPPAUTHTYPE_CHAP
 };
index ccafa5795eff280d7dc74b58ac345d0efda314d2..97618517dc591528a3bcdb7cb62c5e45116835d6 100644 (file)
@@ -115,9 +115,7 @@ slipif_input( struct netif * netif )
   /* Received whole packet. */
   pbuf_realloc(q, recved);
   
-#ifdef LINK_STATS
-  ++lwip_stats.link.recv;
-#endif /* LINK_STATS */         
+  LINK_STATS_INC(link.recv);
   
   LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
   return q;
@@ -141,16 +139,13 @@ slipif_input( struct netif * netif )
   LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
   p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
 
-#ifdef LINK_STATS           
   if (p == NULL) {
-    ++lwip_stats.link.drop;
+    LINK_STATS_INC(link.drop);
     LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
   }
-#endif /* LINK_STATS */                  
   
   if (q != NULL) {
-    pbuf_chain(q, p);
-    pbuf_free(p);
+    pbuf_cat(q, p);
   } else {
     q = p;
   }