diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-09-02 21:58:35 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-09-02 21:58:35 +0000 |
commit | 9a272c38fb40781171f7b4d054430f2c0be730c0 (patch) | |
tree | 892d21bc1008301a5f07a8634cf5cb227f563dc6 /nuttx/net | |
parent | 8e6fadad87d3220628d412fee845ad0b0cfb697f (diff) | |
download | px4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.tar.gz px4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.tar.bz2 px4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.zip |
Implements basic TCP connection logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@326 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net')
-rw-r--r-- | nuttx/net/Makefile | 1 | ||||
-rw-r--r-- | nuttx/net/bind.c | 25 | ||||
-rw-r--r-- | nuttx/net/connect.c | 74 | ||||
-rw-r--r-- | nuttx/net/net_internal.h | 2 | ||||
-rw-r--r-- | nuttx/net/socket.c | 16 | ||||
-rw-r--r-- | nuttx/net/uip/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/net/uip/uip-internal.h | 86 | ||||
-rw-r--r-- | nuttx/net/uip/uip-tcpconn.c | 405 | ||||
-rw-r--r-- | nuttx/net/uip/uip-udpconn.c | 170 | ||||
-rw-r--r-- | nuttx/net/uip/uip.c | 565 |
10 files changed, 998 insertions, 348 deletions
diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile index 9caa4f8ff..25b5c46df 100644 --- a/nuttx/net/Makefile +++ b/nuttx/net/Makefile @@ -34,6 +34,7 @@ ############################################################ -include $(TOPDIR)/Make.defs +CFLAGS += -I./uip MKDEP = $(TOPDIR)/tools/mkdeps.sh diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c index daeb70a87..332214d33 100644 --- a/nuttx/net/bind.c +++ b/nuttx/net/bind.c @@ -1,5 +1,5 @@ /**************************************************************************** - * bind.c + * net/bind.c * * Copyright (C) 2007 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> @@ -82,9 +82,14 @@ * ****************************************************************************/ -int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; +#else + FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; +#endif int err; /* Verify that the sockfd corresponds to valid, allocated socket */ @@ -95,16 +100,28 @@ int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) goto errout; } + /* Verify that a valid address has been provided */ + +#ifdef CONFIG_NET_IPv6 + if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) +#else + if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + /* Perform the binding depending on the protocol type */ switch (psock->s_type) { case SOCK_STREAM: - /* Put TCP/IP binding logic here */ +#warning Put TCP/IP binding logic here break; #ifdef CONFIG_NET_UDP case SOCK_DGRAM: - /* Put UDP binding logic here */ +#warning Put UDP binding logic here break; #endif default: diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c index 5cff6210e..2fcb8bc79 100644 --- a/nuttx/net/connect.c +++ b/nuttx/net/connect.c @@ -1,5 +1,5 @@ /**************************************************************************** - * connect.c + * net/connect.c * * Copyright (C) 2007 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> @@ -44,6 +44,8 @@ #include <sys/socket.h> #include <errno.h> +#include "net_internal.h" + /**************************************************************************** * Global Functions ****************************************************************************/ @@ -117,9 +119,75 @@ * ****************************************************************************/ -int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - *get_errno_ptr() = ENOSYS; + FAR struct socket *psock = sockfd_socket(sockfd); +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; +#else + FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; +#endif + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Verify that a valid address has been provided */ + +#ifdef CONFIG_NET_IPv6 + if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) +#else + if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + + /* Perform the binding depending on the protocol type */ + switch (psock->s_type) + { + case SOCK_STREAM: + { + int ret = uip_tcpconnect(psock->s_conn, inaddr); + if (ret < 0) + { + err = -ret; + goto errout; + } + } + break; + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: +#warning Put UDP connect logic here +#if 0 + { + int ret = uip_udpconnect(psock->s_conn, inaddr); + if (ret < 0) + { + err = -ret; + goto errout; + } + } + break; +#endif +#endif + default: + err = EBADF; + goto errout; + } + + err = ENOSYS; + /*return OK;*/ + +errout: + *get_errno_ptr() = err; return ERROR; } diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h index d45dcef7d..2bc7e4d7d 100644 --- a/nuttx/net/net_internal.h +++ b/nuttx/net/net_internal.h @@ -45,6 +45,8 @@ #include <nuttx/net.h> +#include "net_internal.h" + /**************************************************************************** * Definitions ****************************************************************************/ diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c index 8fe3e395a..ad3ef1e92 100644 --- a/nuttx/net/socket.c +++ b/nuttx/net/socket.c @@ -1,5 +1,5 @@ /**************************************************************************** - * socket.c + * net/socket.c * * Copyright (C) 2007 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> @@ -129,15 +129,25 @@ int socket(int domain, int type, int protocol) /* Initialize the socket structure */ -#ifdef CONFIG_NET_UDP psock = sockfd_socket(sockfd); if (psock) { /* Save the protocol type */ psock->s_type = type; + + /* Allocate a TCP connection structure */ + + psock->s_conn = uip_tcpalloc(); + if (!psock->s_conn) + { + /* Failed to reserve a connection structure */ + + sockfd_release(sockfd); + err = ENFILE; + goto errout; + } } -#endif return sockfd; diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs index 85d61d0d9..716682547 100644 --- a/nuttx/net/uip/Make.defs +++ b/nuttx/net/uip/Make.defs @@ -34,5 +34,5 @@ ############################################################################ UIP_ASRCS = -UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-wait.c +UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-tcpconn.c uip-wait.c diff --git a/nuttx/net/uip/uip-internal.h b/nuttx/net/uip/uip-internal.h new file mode 100644 index 000000000..987b650c7 --- /dev/null +++ b/nuttx/net/uip/uip-internal.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * net/uip/uip-internal.h + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * This logic was leveraged from uIP which also has a BSD-style license: + * + * Author Adam Dunkels <adam@dunkels.com> + * Copyright (c) 2001-2003, Adam Dunkels. + * 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. + * + ****************************************************************************/ + +#ifndef __UIP_INTERNAL_H +#define __UIP_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <sys/types.h> + +/**************************************************************************** + * Public Macro Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_tcp_sequence[] is used to generate TCP sequence numbers */ + +extern uint8 g_tcp_sequence[4]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Defined in uip_tcpconn.c *************************************************/ + +EXTERN void uip_tcpinit(void); +EXTERN struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf); +EXTERN void uip_tcpnextsequence(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __UIP_INTERNAL_H */ diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c new file mode 100644 index 000000000..c877de2c4 --- /dev/null +++ b/nuttx/net/uip/uip-tcpconn.c @@ -0,0 +1,405 @@ +/**************************************************************************** + * uip_tcpbind.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#ifdef CONFIG_NET + +#include <sys/types.h> +#include <string.h> +#include <arch/irq.h> + +#include <net/uip/uipopt.h> +#include <net/uip/uip.h> +#include <net/uip/uip-arch.h> + +#include "uip-internal.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_tcp_sequence[] is used to generate TCP sequence numbers */ + +uint8 g_tcp_sequence[4]; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all uIP connections. */ + +static struct uip_conn g_tcp_connections[UIP_CONNS]; + +/* Last port used by a TCP connection connection. */ + +static uint16 g_last_tcp_port; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Given a port number, find the socket bound to the port number. + * Primary use: to determine if a port number is available. + */ + +static struct uip_conn *uip_find_conn(uint16 portno) +{ + struct uip_conn *conn; + int i; + + /* Check if this port number is already in use, and if so try to find + * another one. + */ + + for (i = 0; i < UIP_CONNS; i++) + { + conn = &g_tcp_connections[i]; + if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(g_last_tcp_port)) + { + /* The portnumber is in use */ + + return conn; + } + } + + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_tcpinit() + * + * Description: + * Initialize the TCP/IP connection structures. Called only from the UIP + * layer. + * + ****************************************************************************/ + +void uip_tcpinit(void) +{ + int i; + for (i = 0; i < UIP_CONNS; i++) + { + g_tcp_connections[i].tcpstateflags = UIP_CLOSED; + } + + g_last_tcp_port = 1024; +} + +/**************************************************************************** + * Name: uip_tcpalloc() + * + * Description: + * Find a free TCP/IP connection structure and allocate it + * for use. This is normally something done by the implementation of the + * socket() API but is also called from the interrupt level when a TCP + * packet is received while "listening" + * + ****************************************************************************/ + +struct uip_conn *uip_tcpalloc(void) +{ +#if 0 /* Revisit */ + struct uip_conn *oldest = NULL; +#endif + irqstate_t flags; + unsigned int i; + + /* Because this routine is called from both interrupt level and + * and from user level, we have not option but to disable interrupts + * while accessing g_tcp_connections[]; + */ + + flags = irqsave(); + + /* Check if there are any available connections. */ + + for (i = 0; i < UIP_CONNS; i++) + { + /* First, check if any connections structures are marked as + * CLOSED in the table of pre-allocated connection structures. + */ + + if (g_tcp_connections[i].tcpstateflags == UIP_CLOSED) + { + /* We found an unused structure. Mark as allocated, but not + * initialized. + */ + + memset(&g_tcp_connections[i], 0, sizeof(struct uip_conn)); + g_tcp_connections[i].tcpstateflags = UIP_ALLOCATED; + + irqrestore(flags); + return &g_tcp_connections[i]; + } + +#if 0 /* Revisit */ + /* As a fallback, check for connection structures in the TIME_WAIT + * state. If no CLOSED connections are found, then take the oldest + */ + + if (g_tcp_connections[i].tcpstateflags == UIP_TIME_WAIT) + { + if (!oldest || g_tcp_connections[i].timer > oldest->timer) + { + oldest = &g_tcp_connections[i]; + } + } + } + return oldest; +#else + } + + irqrestore(flags); + return NULL; +#endif +} + +/**************************************************************************** + * Name: uip_tcpfree() + * + * Description: + * Free a connection structure that is no longer in use. This should be + * done by the implementation of close() + * + ****************************************************************************/ + +void uip_tcpfree(struct uip_conn *conn) +{ + /* this action is atomic and should require no special protetion */ + + conn->tcpstateflags = UIP_CLOSED; +} + +/**************************************************************************** + * Name: uip_tcpactive() + * + * Description: + * Find a connection structure that is the appropriate + * connection to be used withi the provided TCP/IP header + * + * Assumptions: + * This function is called from UIP logic at interrupt level + * + ****************************************************************************/ + +struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) +{ + struct uip_conn *conn; + for (conn = g_tcp_connections; conn <= &g_tcp_connections[UIP_CONNS - 1]; conn++) + { + /* Find an open connection matching the tcp input */ + + if (conn->tcpstateflags != UIP_CLOSED && + buf->destport == conn->lport && buf->srcport == conn->rport && + uip_ipaddr_cmp(buf->srcipaddr, conn->ripaddr)) + { + return conn; + } + } + return NULL; +} + +/**************************************************************************** + * Name: uip_tcppoll() + * + * Description: + * Periodic processing for a connection identified by its number. + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called by the UIP + * device driver when the periodic uIP timer goes off. It should be + * called for every connection, regardless of whether they are open of + * closed. + * + * Assumptions: + * This function is called from the CAN device driver may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +void uip_tcppoll(unsigned int conn) +{ + uip_conn = &g_tcp_connections[conn]; + uip_interrupt(UIP_TIMER); +} + +/**************************************************************************** + * Name: uip_tcpactive() + * + * Description: + * Increment the TCP/IP sequence number + * + * Assumptions: + * This function is called from the interrupt level + * + ****************************************************************************/ + +void uip_tcpnextsequence(void) +{ + /* This inplements a byte-by-byte big-endian increment */ + + if (++g_tcp_sequence[3] == 0) + { + if (++g_tcp_sequence[2] == 0) + { + if (++g_tcp_sequence[1] == 0) + { + ++g_tcp_sequence[0]; + } + } + } +} + +/**************************************************************************** + * Name: uip_tcpbind() + * + * Description: + * This function implements the UIP specific parts of the standard TCP + * bind() operation. + * + * Assumptions: + * This function is called from normal user level code. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr) +#else +int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr) +#endif +{ +#warning "Need to implement bind logic" + return ERROR; +} + +/**************************************************************************** + * Name: uip_tcpbind() + * + * Description: + * This function implements the UIP specific parts of the standard + * TCP connect() operation: It connects to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It uses the connection structure that was + * allocated by a preceding socket() call. It sets the connection to + * the SYN_SENT state and sets the retransmission timer to 0. This will + * cause a TCP SYN segment to be sent out the next time this connection + * is periodically processed, which usually is done within 0.5 seconds + * after the call to uip_tcpconnect(). + * + * Assumptions: + * This function is called from normal user level code. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr ) +#else +int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr ) +#endif +{ + uint16 port; + int i; + + /* If the TCP port has not alread been bound to a local port, then select + * one now. + */ + + port = ntohs(conn->lport); + if (port == 0) + { + /* No local port assigned. Loop until we find a valid listen port number\ + * that is not being used by any other connection. + */ + + do + { + /* Guess that the next available port number will be the one after + * the last port number assigned. + */ +#warning "This need protection from other threads and from interrupts" + port = ++g_last_tcp_port; + + /* Make sure that the port number is within range */ + + if (g_last_tcp_port >= 32000) + { + g_last_tcp_port = 4096; + } + } + while (uip_find_conn(g_last_tcp_port)); + } + + /* Initialize and return the connection structure, bind it to the port number */ + + conn->tcpstateflags = UIP_SYN_SENT; + + conn->snd_nxt[0] = g_tcp_sequence[0]; + conn->snd_nxt[1] = g_tcp_sequence[1]; + conn->snd_nxt[2] = g_tcp_sequence[2]; + conn->snd_nxt[3] = g_tcp_sequence[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons(port); + + /* The sockaddr port is 16 bits and already in network order */ + + conn->rport = addr->sin_port; + + /* The sockaddr address is 32-bits in network order. */ + + uip_ipaddr_copy(&conn->ripaddr, addr->sin_addr.s_addr); + return OK; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip-udpconn.c b/nuttx/net/uip/uip-udpconn.c new file mode 100644 index 000000000..3b7f06fa6 --- /dev/null +++ b/nuttx/net/uip/uip-udpconn.c @@ -0,0 +1,170 @@ +/************************************************************ + * uip-udpconn.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ************************************************************/ + +/************************************************************ + * Compilation Switches + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include <nuttx/config.h> +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Public Functions + ************************************************************/ + +struct uip_udp_conn *uip_udpalloc(void); +void uip_udpfree(struct uip_udp_conn *conn); + +#ifdef CONFIG_NET_IPv6 +int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr); +#else +int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr); +#endif + +#ifdef CONFIG_NET_IPv6 +int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr ) +#else +int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr) +#endif +{ + uint16 ipaddr[2]; + + if (pdhcpc->state == STATE_INITIAL) + { + uip_ipaddr(ipaddr, 0,0,0,0); + uip_sethostaddr(ipaddr); + } + return OK; +} + +/* Set up a new UDP connection. + * + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udp_bind() call, after the uip_udp_new() function has been + * called. + * + * Example: + * + * uip_ipaddr_t addr; + * struct uip_udp_conn *c; + * + * uip_ipaddr(&addr, 192,168,2,1); + * c = uip_udp_new(&addr, HTONS(12345)); + * if(c != NULL) { + * uip_udp_bind(c, HTONS(12344)); + * } + * + * ripaddr The IP address of the remote host. + * + * rport The remote port number in network byte order. + * + * Return: The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ + +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport) +{ + struct uip_udp_conn *conn; + int i; + + /* Find an unused local port number. Loop until we find a valid listen port + * number that is not being used by any other connection. + */ + + do + { + /* Guess that the next available port number will be the one after + * the last port number assigned. + */ + + ++g_last_udp_port; + + /* Make sure that the port number is within range */ + if (g_last_udp_port >= 32000) + { + g_last_udp_port = 4096; + } + } + while (uip_find_udp_conn(g_last_udp_port)); + + /* Now find an available UDP connection structure */ + + conn = 0; + for (i = 0; i < UIP_UDP_CONNS; i++) + { + if (uip_udp_conns[c].lport == 0) + { + conn = &uip_udp_conns[c]; + break; + } + } + + /* Return an error if no connection is available */ + + if (conn == 0) + { + return 0; + } + + /* Initialize and return the connection structure, bind it to the port number */ + + conn->lport = HTONS(g_last_udp_port); + conn->rport = rport; + + if (ripaddr == NULL) + { + memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); + } + else + { + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + } + + conn->ttl = UIP_TTL; + + return conn; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip.c b/nuttx/net/uip/uip.c index 7fa2e3b7e..830f34551 100644 --- a/nuttx/net/uip/uip.c +++ b/nuttx/net/uip/uip.c @@ -93,6 +93,8 @@ extern void uip_log(char *msg); # define UIP_LOG(m) #endif /* UIP_LOGGING == 1 */ +#include "uip-internal.h" + /**************************************************************************** * Definitions ****************************************************************************/ @@ -175,11 +177,9 @@ uint16 uip_flags; /* The uip_flags variable is used for communica * program. */ struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */ -struct uip_conn uip_conns[UIP_CONNS]; - /* The uip_conns array holds all TCP connections. */ uint16 uip_listenports[UIP_LISTENPORTS]; /* The uip_listenports list all currently listning ports. */ - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP struct uip_udp_conn *uip_udp_conn; struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; #endif /* CONFIG_NET_UDP */ @@ -222,11 +222,10 @@ struct uip_eth_addr uip_ethaddr = {{ 0,0,0,0,0,0 }}; static uint16 ipid; /* Ths ipid variable is an increasing number that is * used for the IP ID field. */ -static uint8 iss[4]; /* The iss variable is used for the TCP initial - * sequence number. */ - -static uint16 lastport; /* Keeps track of the last port used for a new +#ifdef CONFIG_NET_UDP +static uint16 g_last_udp_port; /* Keeps track of the last port used for a new * connection. */ +#endif /* Temporary variables. */ static uint8 c, opt; @@ -236,38 +235,6 @@ static uint16 tmp16; * Private Functions ****************************************************************************/ -#if !UIP_ARCH_ADD32 -static void uip_add32(uint8 *op32, uint16 op16) -{ - uip_acc32[3] = op32[3] + (op16 & 0xff); - uip_acc32[2] = op32[2] + (op16 >> 8); - uip_acc32[1] = op32[1]; - uip_acc32[0] = op32[0]; - - if (uip_acc32[2] < (op16 >> 8)) - { - ++uip_acc32[1]; - if (uip_acc32[1] == 0) - { - ++uip_acc32[0]; - } - } - - if (uip_acc32[3] < (op16 & 0xff)) - { - ++uip_acc32[2]; - if (uip_acc32[2] == 0) - { - ++uip_acc32[1]; - if (uip_acc32[1] == 0) - { - ++uip_acc32[0]; - } - } - } -} -#endif /* UIP_ARCH_ADD32 */ - #if !UIP_ARCH_CHKSUM static uint16 chksum(uint16 sum, const uint8 *data, uint16 len) { @@ -340,34 +307,7 @@ static uint16 uip_icmp6chksum(void) #endif /* UIP_ARCH_CHKSUM */ -/* Given a port number, find the socket bound to the port number. - * Primary use: to determine if a port number is available. - */ - -struct uip_conn *uip_find_conn( uint16 portno ) -{ - struct uip_conn *conn; - int i; - - /* Check if this port number is already in use, and if so try to find - * another one. - */ - - for (i = 0; i < UIP_CONNS; i++) - { - conn = &uip_conns[i]; - if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport)) - { - /* The portnumber is in use */ - - return conn; - } - } - - return NULL; -} - - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP struct uip_udp_conn *uip_find_udp_conn( uint16 portno ) { struct uip_udp_conn *conn; @@ -375,7 +315,7 @@ struct uip_udp_conn *uip_find_udp_conn( uint16 portno ) for (i = 0; i < UIP_UDP_CONNS; i++) { - if (uip_udp_conns[i].lport == htons(lastport)) + if (uip_udp_conns[i].lport == htons(g_last_udp_port)) { return conn; } @@ -398,6 +338,38 @@ void uip_setipid(uint16 id) /* Calculate the Internet checksum over a buffer. */ +#if !UIP_ARCH_ADD32 +void uip_add32(uint8 *op32, uint16 op16) +{ + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if (uip_acc32[2] < (op16 >> 8)) + { + ++uip_acc32[1]; + if (uip_acc32[1] == 0) + { + ++uip_acc32[0]; + } + } + + if (uip_acc32[3] < (op16 & 0xff)) + { + ++uip_acc32[2]; + if (uip_acc32[2] == 0) + { + ++uip_acc32[1]; + if (uip_acc32[1] == 0) + { + ++uip_acc32[0]; + } + } + } +} +#endif /* UIP_ARCH_ADD32 */ + #if !UIP_ARCH_CHKSUM uint16 uip_chksum(uint16 *data, uint16 len) { @@ -426,7 +398,7 @@ uint16 uip_tcpchksum(void) /* Calculate the UDP checksum of the packet in uip_buf and uip_appdata. */ - #ifdef CONFIG_NET_UDP_CHECKSUMS +#ifdef CONFIG_NET_UDP_CHECKSUMS uint16 uip_udpchksum(void) { return upper_layer_chksum(UIP_PROTO_UDP); @@ -441,17 +413,19 @@ void uip_init(void) uip_listenports[c] = 0; } - for (c = 0; c < UIP_CONNS; ++c) - { - uip_conns[c].tcpstateflags = UIP_CLOSED; - } - lastport = 1024; + /* Initialize the TCP/IP connection structures */ + + uip_tcpinit(); + + /* Initialize the UDP connection structures */ - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP for (c = 0; c < UIP_UDP_CONNS; ++c) { uip_udp_conns[c].lport = 0; } + + g_last_udp_port = 1024; #endif /* CONFIG_NET_UDP */ /* IPv4 initialization. */ @@ -460,83 +434,6 @@ void uip_init(void) #endif /* UIP_FIXEDADDR */ } -struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 rport) -{ - struct uip_conn *conn, *cconn; - int i; - - /* Find an unused local port number. Loop until we find a valid listen port - * number that is not being used by any other connection. - */ - - do - { - /* Guess that the next available port number will be the one after - * the last port number assigned. - */ - - ++lastport; - - /* Make sure that the port number is within range */ - if (lastport >= 32000) - { - lastport = 4096; - } - } - while (uip_find_conn(lastport)); - - /* Now find an available connection structure */ - - conn = 0; - for (i = 0; i < UIP_CONNS; i++) - { - cconn = &uip_conns[i]; - if (cconn->tcpstateflags == UIP_CLOSED) - { - conn = cconn; - break; - } - - if (cconn->tcpstateflags == UIP_TIME_WAIT) - { - if (conn == 0 || cconn->timer > conn->timer) - { - conn = cconn; - } - } - } - - /* Return an error if no connection is available */ - - if (conn == 0) - { - return 0; - } - - /* Initialize and return the connection structure, bind it to the port number */ - - conn->tcpstateflags = UIP_SYN_SENT; - - conn->snd_nxt[0] = iss[0]; - conn->snd_nxt[1] = iss[1]; - conn->snd_nxt[2] = iss[2]; - conn->snd_nxt[3] = iss[3]; - - conn->initialmss = conn->mss = UIP_TCP_MSS; - - conn->len = 1; /* TCP length of the SYN is one. */ - conn->nrtx = 0; - conn->timer = 1; /* Send the SYN next time around. */ - conn->rto = UIP_RTO; - conn->sa = 0; - conn->sv = 16; /* Initial value of the RTT variance. */ - conn->lport = htons(lastport); - conn->rport = rport; - uip_ipaddr_copy(&conn->ripaddr, ripaddr); - - return conn; -} - #ifdef CONFIG_NET_UDP struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport) { @@ -553,15 +450,15 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport) * the last port number assigned. */ - ++lastport; + ++g_last_udp_port; /* Make sure that the port number is within range */ - if (lastport >= 32000) + if (g_last_udp_port >= 32000) { - lastport = 4096; + g_last_udp_port = 4096; } } - while (uip_find_udp_conn(lastport)); + while (uip_find_udp_conn(g_last_udp_port)); /* Now find an available UDP connection structure */ @@ -584,7 +481,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport) /* Initialize and return the connection structure, bind it to the port number */ - conn->lport = HTONS(lastport); + conn->lport = HTONS(g_last_udp_port); conn->rport = rport; if (ripaddr == NULL) @@ -616,15 +513,17 @@ void uip_unlisten(uint16 port) void uip_listen(uint16 port) { - for (c = 0; c < UIP_LISTENPORTS; ++c) { - if (uip_listenports[c] == 0) { - uip_listenports[c] = port; - return; + for (c = 0; c < UIP_LISTENPORTS; ++c) + { + if (uip_listenports[c] == 0) + { + uip_listenports[c] = port; + return; + } } - } } -/* XXX: IP fragment reassembly: not well-tested. */ +/* IP fragment reassembly: not well-tested. */ #if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) @@ -644,113 +543,133 @@ static uint8 uip_reass(void) uint16 i; /* If ip_reasstmr is zero, no packet is present in the buffer, so we - write the IP header of the fragment into the reassembly - buffer. The timer is updated with the maximum age. */ - if (uip_reasstmr == 0) { - memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); - uip_reasstmr = UIP_REASS_MAXAGE; - uip_reassflags = 0; - /* Clear the bitmap. */ - memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); - } + * write the IP header of the fragment into the reassembly + * buffer. The timer is updated with the maximum age. + */ - /* Check if the incoming fragment matches the one currently present - in the reasembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if (BUF->srcipaddr[0] == FBUF->srcipaddr[0] && - BUF->srcipaddr[1] == FBUF->srcipaddr[1] && - BUF->destipaddr[0] == FBUF->destipaddr[0] && - BUF->destipaddr[1] == FBUF->destipaddr[1] && - BUF->ipid[0] == FBUF->ipid[0] && - BUF->ipid[1] == FBUF->ipid[1]) { - - len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; - offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; - - /* If the offset or the offset + fragment length overflows the - reassembly buffer, we discard the entire packet. */ - if (offset > UIP_REASS_BUFSIZE || - offset + len > UIP_REASS_BUFSIZE) { - uip_reasstmr = 0; - goto nullreturn; + if (uip_reasstmr == 0) + { + memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + + /* Clear the bitmap. */ + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); } - /* Copy the fragment into the reassembly buffer, at the right - offset. */ - memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], - (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), - len); + /* Check if the incoming fragment matches the one currently present + * in the reasembly buffer. If so, we proceed with copying the + * fragment into the buffer. + */ + + if (BUF->srcipaddr[0] == FBUF->srcipaddr[0] && BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && BUF->ipid[1] == FBUF->ipid[1]) + { + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + * reassembly buffer, we discard the entire packet. + */ + + if (offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE) + { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right offset. */ + + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), len); /* Update the bitmap. */ - if (offset / (8 * 8) == (offset + len) / (8 * 8)) { - /* If the two endpoints are in the same byte, we only update - that byte. */ - - uip_reassbitmap[offset / (8 * 8)] |= - bitmap_bits[(offset / 8 ) & 7] & - ~bitmap_bits[((offset + len) / 8 ) & 7]; - } else { - /* If the two endpoints are in different bytes, we update the - bytes in the endpoints and fill the stuff inbetween with - 0xff. */ - uip_reassbitmap[offset / (8 * 8)] |= - bitmap_bits[(offset / 8 ) & 7]; - for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { - uip_reassbitmap[i] = 0xff; - } - uip_reassbitmap[(offset + len) / (8 * 8)] |= - ~bitmap_bits[((offset + len) / 8 ) & 7]; - } - /* If this fragment has the More Fragments flag set to zero, we - know that this is the last fragment, so we can calculate the - size of the entire packet. We also set the - IP_REASS_FLAG_LASTFRAG flag to indicate that we have received - the final fragment. */ + if (offset / (8 * 8) == (offset + len) / (8 * 8)) + { + /* If the two endpoints are in the same byte, we only update that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & ~bitmap_bits[((offset + len) / 8 ) & 7]; - if ((BUF->ipoffset[0] & IP_MF) == 0) { - uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; - uip_reasslen = offset + len; - } + } + else + { + /* If the two endpoints are in different bytes, we update the bytes + * in the endpoints and fill the stuff inbetween with 0xff. + */ - /* Finally, we check if we have a full packet in the buffer. We do - this by checking if we have the last fragment and if all bits - in the bitmap are set. */ - if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { - /* Check all bytes up to and including all but the last byte in - the bitmap. */ - for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { - if (uip_reassbitmap[i] != 0xff) { - goto nullreturn; - } + uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8 ) & 7]; + for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) + { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= ~bitmap_bits[((offset + len) / 8 ) & 7]; } - /* Check the last byte in the bitmap. It should contain just the - right amount of bits. */ - if (uip_reassbitmap[uip_reasslen / (8 * 8)] != - (uint8)~bitmap_bits[uip_reasslen / 8 & 7]) { - goto nullreturn; + /* If this fragment has the More Fragments flag set to zero, we know that + * this is the last fragment, so we can calculate the size of the entire + * packet. We also set the IP_REASS_FLAG_LASTFRAG flag to indicate that + * we have received the final fragment. + */ + + if ((BUF->ipoffset[0] & IP_MF) == 0) + { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; } - /* If we have come this far, we have a full packet in the - buffer, so we allocate a pbuf and copy the packet into it. We - also reset the timer. */ - uip_reasstmr = 0; - memcpy(BUF, FBUF, uip_reasslen); - - /* Pretend to be a "normal" (i.e., not fragmented) IP packet - from now on. */ - BUF->ipoffset[0] = BUF->ipoffset[1] = 0; - BUF->len[0] = uip_reasslen >> 8; - BUF->len[1] = uip_reasslen & 0xff; - BUF->ipchksum = 0; - BUF->ipchksum = ~(uip_ipchksum()); - - return uip_reasslen; - } + /* Finally, we check if we have a full packet in the buffer. We do this + * by checking if we have the last fragment and if all bits in the bitmap + * are set. + */ + + if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) + { + /* Check all bytes up to and including all but the last byte in + * the bitmap. + */ + + for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) + { + if (uip_reassbitmap[i] != 0xff) + { + goto nullreturn; + } + } + + /* Check the last byte in the bitmap. It should contain just the + * right amount of bits. + */ + + if (uip_reassbitmap[uip_reasslen / (8 * 8)] != (uint8)~bitmap_bits[uip_reasslen / 8 & 7]) + { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the buffer, + * so we allocate a pbuf and copy the packet into it. We also reset + * the timer. + */ + + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet from + * now on. + */ + + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } } - nullreturn: +nullreturn: return 0; } #endif /* UIP_REASSEMBLY */ @@ -768,7 +687,7 @@ void uip_interrupt(uint8 flag) { register struct uip_conn *uip_connr = uip_conn; - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP if (flag == UIP_UDP_SEND_CONN) { goto udp_send; @@ -805,22 +724,13 @@ void uip_interrupt(uint8 flag) } #endif /* UIP_REASSEMBLY */ - /* Increase the initial sequence number */ + /* Increase the TCP sequence number */ - if (++iss[3] == 0) - { - if (++iss[2] == 0) - { - if (++iss[1] == 0) - { - ++iss[0]; - } - } - } + uip_tcpnextsequence(); /* Reset the length variables. */ - uip_len = 0; + uip_len = 0; uip_slen = 0; /* Check if the connection is in a state in which we simply wait @@ -935,7 +845,7 @@ void uip_interrupt(uint8 flag) goto drop; } - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP if (flag == UIP_UDP_TIMER) { if (uip_udp_conn->lport != 0) @@ -1105,7 +1015,7 @@ void uip_interrupt(uint8 flag) goto tcp_input; } - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP if (BUF->proto == UIP_PROTO_UDP) { goto udp_input; @@ -1247,14 +1157,14 @@ void uip_interrupt(uint8 flag) #endif /* !CONFIG_NET_IPv6 */ - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP /* UDP input processing. */ udp_input: /* UDP processing is really just a hack. We don't do anything to the UDP/IP headers, but let the UDP application do all the hard work. If the application sets uip_slen, it has a packet to send. */ - #ifdef CONFIG_NET_UDP_CHECKSUMS +#ifdef CONFIG_NET_UDP_CHECKSUMS uip_len = uip_len - UIP_IPUDPH_LEN; uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; if (UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) @@ -1269,9 +1179,8 @@ void uip_interrupt(uint8 flag) #endif /* UIP_UDP_CHECKSUMS */ /* Demultiplex this UDP packet between the UDP "connections". */ - for (uip_udp_conn = &uip_udp_conns[0]; - uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; - ++uip_udp_conn) + + for (uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; uip_udp_conn++) { /* If the local UDP port is non-zero, the connection is considered * to be used. If so, the local port number is checked against the @@ -1282,13 +1191,12 @@ void uip_interrupt(uint8 flag) * address of the packet is checked. */ - if (uip_udp_conn->lport != 0 && - UDPBUF->destport == uip_udp_conn->lport && + if (uip_udp_conn->lport != 0 && UDPBUF->destport == uip_udp_conn->lport && (uip_udp_conn->rport == 0 || - UDPBUF->srcport == uip_udp_conn->rport) && - (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || - uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || - uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) + UDPBUF->srcport == uip_udp_conn->rport) && + (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || + uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || + uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) { goto udp_found; } @@ -1336,7 +1244,7 @@ void uip_interrupt(uint8 flag) uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; - #ifdef CONFIG_NET_UDP_CHECKSUMS +#ifdef CONFIG_NET_UDP_CHECKSUMS /* Calculate UDP checksum. */ UDPBUF->udpchksum = ~(uip_udpchksum()); if (UDPBUF->udpchksum == 0) @@ -1357,30 +1265,27 @@ void uip_interrupt(uint8 flag) if (uip_tcpchksum() != 0xffff) { /* Compute and check the TCP checksum. */ + UIP_STAT(++uip_stat.tcp.drop); UIP_STAT(++uip_stat.tcp.chkerr); UIP_LOG("tcp: bad checksum."); goto drop; } - /* Demultiplex this segment. */ - /* First check any active connections. */ - for (uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; - ++uip_connr) + /* Demultiplex this segment. First check any active connections. */ + + uip_connr = uip_tcpactive(BUF); + if (uip_connr) { - if (uip_connr->tcpstateflags != UIP_CLOSED && - BUF->destport == uip_connr->lport && - BUF->srcport == uip_connr->rport && - uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) - { - goto found; - } + goto found; } /* If we didn't find and active connection that expected the packet, - either this packet is an old duplicate, or this is a SYN packet - destined for a connection in LISTEN. If the SYN flag isn't set, - it is an old packet and we send a RST. */ + * either this packet is an old duplicate, or this is a SYN packet + * destined for a connection in LISTEN. If the SYN flag isn't set, + * it is an old packet and we send a RST. + */ + if ((BUF->flags & TCP_CTL) != TCP_SYN) { goto reset; @@ -1455,57 +1360,43 @@ void uip_interrupt(uint8 flag) goto tcp_send_noconn; /* This label will be jumped to if we matched the incoming packet - with a connection in LISTEN. In that case, we should create a new - connection and send a SYNACK in return. */ - found_listen: - /* First we check if there are any connections avaliable. Unused - connections are kept in the same table as used connections, but - unused ones have the tcpstate set to CLOSED. Also, connections in - TIME_WAIT are kept track of and we'll use the oldest one if no - CLOSED connections are found. Thanks to Eddie C. Dost for a very - nice algorithm for the TIME_WAIT search. */ - uip_connr = 0; - for (c = 0; c < UIP_CONNS; ++c) - { - if (uip_conns[c].tcpstateflags == UIP_CLOSED) - { - uip_connr = &uip_conns[c]; - break; - } - if (uip_conns[c].tcpstateflags == UIP_TIME_WAIT) - { - if (uip_connr == 0 || uip_conns[c].timer > uip_connr->timer) - { - uip_connr = &uip_conns[c]; - } - } - } + * with a connection in LISTEN. In that case, we should create a new + * connection and send a SYNACK in return. + */ - if (uip_connr == 0) +found_listen: + + /* First allocate a new connection structure */ + + uip_connr = uip_tcpalloc(); + if (!uip_connr) { /* All connections are used already, we drop packet and hope that - the remote end will retransmit the packet at a time when we - have more spare connections. */ + * the remote end will retransmit the packet at a time when we + * have more spare connections. + */ + UIP_STAT(++uip_stat.tcp.syndrop); - UIP_LOG("tcp: found no unused connections."); - goto drop; - } + UIP_LOG("tcp: found no unused connections."); + goto drop; + } uip_conn = uip_connr; /* Fill in the necessary fields for the new connection. */ - uip_connr->rto = uip_connr->timer = UIP_RTO; - uip_connr->sa = 0; - uip_connr->sv = 4; - uip_connr->nrtx = 0; + + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; uip_connr->lport = BUF->destport; uip_connr->rport = BUF->srcport; uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); uip_connr->tcpstateflags = UIP_SYN_RCVD; - uip_connr->snd_nxt[0] = iss[0]; - uip_connr->snd_nxt[1] = iss[1]; - uip_connr->snd_nxt[2] = iss[2]; - uip_connr->snd_nxt[3] = iss[3]; + uip_connr->snd_nxt[0] = g_tcp_sequence[0]; + uip_connr->snd_nxt[1] = g_tcp_sequence[1]; + uip_connr->snd_nxt[2] = g_tcp_sequence[2]; + uip_connr->snd_nxt[3] = g_tcp_sequence[3]; uip_connr->len = 1; /* rcv_nxt should be the seqno from the incoming packet + 1. */ @@ -2119,7 +2010,7 @@ void uip_interrupt(uint8 flag) BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); - #ifdef CONFIG_NET_UDP +#ifdef CONFIG_NET_UDP ip_send_nolen: #endif /* CONFIG_NET_UDP */ |