From cf4575b94a3c65e6535a159fc71fc885aebc2620 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Fri, 2 Aug 2019 14:02:40 -0700 Subject: Fix the LUFA lib to use a submodule instead of just files (#6245) * Remove LUFA files * Update descriptions for newer version of LUFA * Create PR6245.md * Fix CDC(Serial) type errors * Fix missed merge conflict for AUDIO_DTYPE_CSInterface --- lib/lufa/Projects/Webserver/Lib/uip/clock.c | 37 - lib/lufa/Projects/Webserver/Lib/uip/clock.h | 13 - lib/lufa/Projects/Webserver/Lib/uip/timer.c | 128 -- lib/lufa/Projects/Webserver/Lib/uip/timer.h | 87 - lib/lufa/Projects/Webserver/Lib/uip/uip-split.c | 151 -- lib/lufa/Projects/Webserver/Lib/uip/uip-split.h | 104 -- lib/lufa/Projects/Webserver/Lib/uip/uip.c | 1941 --------------------- lib/lufa/Projects/Webserver/Lib/uip/uip.h | 2130 ----------------------- lib/lufa/Projects/Webserver/Lib/uip/uip_arp.c | 432 ----- lib/lufa/Projects/Webserver/Lib/uip/uip_arp.h | 146 -- lib/lufa/Projects/Webserver/Lib/uip/uipopt.h | 740 -------- 11 files changed, 5909 deletions(-) delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/clock.c delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/clock.h delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/timer.c delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/timer.h delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip-split.c delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip-split.h delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip.c delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip.h delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip_arp.c delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uip_arp.h delete mode 100644 lib/lufa/Projects/Webserver/Lib/uip/uipopt.h (limited to 'lib/lufa/Projects/Webserver/Lib/uip') diff --git a/lib/lufa/Projects/Webserver/Lib/uip/clock.c b/lib/lufa/Projects/Webserver/Lib/uip/clock.c deleted file mode 100644 index e71f7209d2..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/clock.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -#include - -#include "clock.h" - -//Counted time -volatile clock_time_t clock_datetime = 0; - -//Overflow interrupt -ISR(TIMER1_COMPA_vect, ISR_BLOCK) -{ - clock_datetime += 1; -} - -//Initialise the clock -void clock_init() -{ - OCR1A = (((F_CPU / 1024) / 100) - 1); - TCCR1B = ((1 << WGM12) | (1 << CS12) | (1 << CS10)); - TIMSK1 = (1 << OCIE1A); -} - -//Return time -clock_time_t clock_time() -{ - clock_time_t time; - - GlobalInterruptDisable(); - time = clock_datetime; - GlobalInterruptEnable(); - - return time; -} - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/clock.h b/lib/lufa/Projects/Webserver/Lib/uip/clock.h deleted file mode 100644 index bbfa4ac0e3..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/clock.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __CLOCK_ARCH_H__ -#define __CLOCK_ARCH_H__ - -#include -#include - -typedef uint16_t clock_time_t; -#define CLOCK_SECOND 100 -void clock_init(void); -clock_time_t clock_time(void); - -#endif /* __CLOCK_ARCH_H__ */ - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/timer.c b/lib/lufa/Projects/Webserver/Lib/uip/timer.c deleted file mode 100644 index eae06f43bd..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/timer.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * \addtogroup timer - * @{ - */ - -/** - * \file - * Timer library implementation. - * \author - * Adam Dunkels - */ - -/* - * Copyright (c) 2004, 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. - * - * This file is part of the uIP TCP/IP stack - * - * Author: Adam Dunkels - * - * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ - */ - -#include "clock.h" -#include "timer.h" - -/*---------------------------------------------------------------------------*/ -/** - * Set a timer. - * - * This function is used to set a timer for a time sometime in the - * future. The function timer_expired() will evaluate to true after - * the timer has expired. - * - * \param t A pointer to the timer - * \param interval The interval before the timer expires. - * - */ -void -timer_set(struct timer *t, clock_time_t interval) -{ - t->interval = interval; - t->start = clock_time(); -} -/*---------------------------------------------------------------------------*/ -/** - * Reset the timer with the same interval. - * - * This function resets the timer with the same interval that was - * given to the timer_set() function. The start point of the interval - * is the exact time that the timer last expired. Therefore, this - * function will cause the timer to be stable over time, unlike the - * timer_restart() function. - * - * \param t A pointer to the timer. - * - * \sa timer_restart() - */ -void -timer_reset(struct timer *t) -{ - t->start += t->interval; -} -/*---------------------------------------------------------------------------*/ -/** - * Restart the timer from the current point in time - * - * This function restarts a timer with the same interval that was - * given to the timer_set() function. The timer will start at the - * current time. - * - * \note A periodic timer will drift if this function is used to reset - * it. For periodic timers, use the timer_reset() function instead. - * - * \param t A pointer to the timer. - * - * \sa timer_reset() - */ -void -timer_restart(struct timer *t) -{ - t->start = clock_time(); -} -/*---------------------------------------------------------------------------*/ -/** - * Check if a timer has expired. - * - * This function tests if a timer has expired and returns true or - * false depending on its status. - * - * \param t A pointer to the timer - * - * \return Non-zero if the timer has expired, zero otherwise. - * - */ -int -timer_expired(struct timer *t) -{ - return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; -} -/*---------------------------------------------------------------------------*/ - -/** @} */ - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/timer.h b/lib/lufa/Projects/Webserver/Lib/uip/timer.h deleted file mode 100644 index 04917e4c52..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/timer.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * \defgroup timer Timer library - * - * The timer library provides functions for setting, resetting and - * restarting timers, and for checking if a timer has expired. An - * application must "manually" check if its timers have expired; this - * is not done automatically. - * - * A timer is declared as a \c struct \c timer and all access to the - * timer is made by a pointer to the declared timer. - * - * \note The timer library uses the \ref clock "Clock library" to - * measure time. Intervals should be specified in the format used by - * the clock library. - * - * @{ - */ - - -/** - * \file - * Timer library header file. - * \author - * Adam Dunkels - */ - -/* - * Copyright (c) 2004, 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. - * - * This file is part of the uIP TCP/IP stack - * - * Author: Adam Dunkels - * - * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ - */ -#ifndef __TIMER_H__ -#define __TIMER_H__ - -#include "clock.h" - -/** - * A timer. - * - * This structure is used for declaring a timer. The timer must be set - * with timer_set() before it can be used. - * - * \hideinitializer - */ -struct timer { - clock_time_t start; - clock_time_t interval; -}; - -void timer_set(struct timer *t, clock_time_t interval); -void timer_reset(struct timer *t); -void timer_restart(struct timer *t); -int timer_expired(struct timer *t); - -#endif /* __TIMER_H__ */ - -/** @} */ - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/uip-split.c b/lib/lufa/Projects/Webserver/Lib/uip/uip-split.c deleted file mode 100644 index 5222a05b63..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/uip-split.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2004, 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. - * - * This file is part of the Contiki operating system. - * - * Author: Adam Dunkels - * - * $Id: uip-split.c,v 1.2 2008/10/14 13:39:12 julienabeille Exp $ - */ - -#include "uip-split.h" - - -#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) - -/*-----------------------------------------------------------------------------*/ -void -uip_split_output(void) -{ -#if UIP_TCP - u16_t tcplen, len1, len2; - - /* We only try to split maximum sized TCP segments. */ - if(BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE) { - - tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; - /* Split the segment in two. If the original packet length was - odd, we make the second packet one byte larger. */ - len1 = len2 = tcplen / 2; - if(len1 + len2 < tcplen) { - ++len2; - } - - /* Create the first packet. This is done by altering the length - field of the IP header and updating the checksums. */ - uip_len = len1 + UIP_TCPIP_HLEN + UIP_LLH_LEN; -#if UIP_CONF_IPV6 - /* For IPv6, the IP length field does not include the IPv6 IP header - length. */ - BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); -#else /* UIP_CONF_IPV6 */ - BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8; - BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff; -#endif /* UIP_CONF_IPV6 */ - - /* Recalculate the TCP checksum. */ - BUF->tcpchksum = 0; - BUF->tcpchksum = ~(uip_tcpchksum()); - -#if !UIP_CONF_IPV6 - /* Recalculate the IP checksum. */ - BUF->ipchksum = 0; - BUF->ipchksum = ~(uip_ipchksum()); -#endif /* UIP_CONF_IPV6 */ - - /* Transmit the first packet. */ -#if UIP_CONF_IPV6 - tcpip_ipv6_output(); -#else - if (USB_CurrentMode == USB_MODE_Device) - RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); - else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); -#endif /* UIP_CONF_IPV6 */ - - /* Now, create the second packet. To do this, it is not enough to - just alter the length field, but we must also update the TCP - sequence number and point the uip_appdata to a new place in - memory. This place is determined by the length of the first - packet (len1). */ - uip_len = len2 + UIP_TCPIP_HLEN + UIP_LLH_LEN; -#if UIP_CONF_IPV6 - /* For IPv6, the IP length field does not include the IPv6 IP header - length. */ - BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); -#else /* UIP_CONF_IPV6 */ - BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8; - BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff; -#endif /* UIP_CONF_IPV6 */ - - memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2); - - uip_add32(BUF->seqno, len1); - BUF->seqno[0] = uip_acc32[0]; - BUF->seqno[1] = uip_acc32[1]; - BUF->seqno[2] = uip_acc32[2]; - BUF->seqno[3] = uip_acc32[3]; - - /* Recalculate the TCP checksum. */ - BUF->tcpchksum = 0; - BUF->tcpchksum = ~(uip_tcpchksum()); - -#if !UIP_CONF_IPV6 - /* Recalculate the IP checksum. */ - BUF->ipchksum = 0; - BUF->ipchksum = ~(uip_ipchksum()); -#endif /* UIP_CONF_IPV6 */ - - /* Transmit the second packet. */ -#if UIP_CONF_IPV6 - tcpip_ipv6_output(); -#else - if (USB_CurrentMode == USB_MODE_Device) - RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); - else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); -#endif /* UIP_CONF_IPV6 */ - return; - } -#endif /* UIP_TCP */ - - /* uip_fw_output();*/ -#if UIP_CONF_IPV6 - tcpip_ipv6_output(); -#else - if (USB_CurrentMode == USB_MODE_Device) - RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); - else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); -#endif /* UIP_CONF_IPV6 */ -} - -/*-----------------------------------------------------------------------------*/ - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/uip-split.h b/lib/lufa/Projects/Webserver/Lib/uip/uip-split.h deleted file mode 100644 index 0c768ce40a..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/uip-split.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2004, 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. - * - * This file is part of the Contiki operating system. - * - * Author: Adam Dunkels - * - * $Id: uip-split.h,v 1.1 2006/06/17 22:41:19 adamdunkels Exp $ - */ -/** - * \addtogroup uip - * @{ - */ - -/** - * \defgroup uipsplit uIP TCP throughput booster hack - * @{ - * - * The basic uIP TCP implementation only allows each TCP connection to - * have a single TCP segment in flight at any given time. Because of - * the delayed ACK algorithm employed by most TCP receivers, uIP's - * limit on the amount of in-flight TCP segments seriously reduces the - * maximum achievable throughput for sending data from uIP. - * - * The uip-split module is a hack which tries to remedy this - * situation. By splitting maximum sized outgoing TCP segments into - * two, the delayed ACK algorithm is not invoked at TCP - * receivers. This improves the throughput when sending data from uIP - * by orders of magnitude. - * - * The uip-split module uses the uip-fw module (uIP IP packet - * forwarding) for sending packets. Therefore, the uip-fw module must - * be set up with the appropriate network interfaces for this module - * to work. - */ - - -/** - * \file - * Module for splitting outbound TCP segments in two to avoid the - * delayed ACK throughput degradation. - * \author - * Adam Dunkels - * - */ - -#ifndef __UIP_SPLIT_H__ -#define __UIP_SPLIT_H__ - -#include -#include - -#include "../../USBHostMode.h" - -#include - -/** - * Handle outgoing packets. - * - * This function inspects an outgoing packet in the uip_buf buffer and - * sends it out using the uip_fw_output() function. If the packet is a - * full-sized TCP segment it will be split into two segments and - * transmitted separately. This function should be called instead of - * the actual device driver output function, or the uip_fw_output() - * function. - * - * The headers of the outgoing packet is assumed to be in the uip_buf - * buffer and the payload is assumed to be wherever uip_appdata - * points. The length of the outgoing packet is assumed to be in the - * uip_len variable. - * - */ -void uip_split_output(void); -void uip_add32(u8_t *op32, u16_t op16); -#endif /* __UIP_SPLIT_H__ */ - -/** @} */ -/** @} */ - diff --git a/lib/lufa/Projects/Webserver/Lib/uip/uip.c b/lib/lufa/Projects/Webserver/Lib/uip/uip.c deleted file mode 100644 index fead75775c..0000000000 --- a/lib/lufa/Projects/Webserver/Lib/uip/uip.c +++ /dev/null @@ -1,1941 +0,0 @@ -#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/ - -/** - * \addtogroup uip - * @{ - */ - -/** - * \file - * The uIP TCP/IP stack code. - * \author Adam Dunkels - */ - -/* - * 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: uip.c,v 1.15 2008/10/15 08:08:32 adamdunkels Exp $ - * - */ - -/* - * uIP is a small implementation of the IP, UDP and TCP protocols (as - * well as some basic ICMP stuff). The implementation couples the IP, - * UDP, TCP and the application layers very tightly. To keep the size - * of the compiled code down, this code frequently uses the goto - * statement. While it would be possible to break the uip_process() - * function into many smaller functions, this would increase the code - * size because of the overhead of parameter passing and the fact that - * the optimizer would not be as efficient. - * - * The principle is that we have a small buffer, called the uip_buf, - * in which the device driver puts an incoming packet. The TCP/IP - * stack parses the headers in the packet, and calls the - * application. If the remote host has sent data to the application, - * this data is present in the uip_buf and the application read the - * data from there. It is up to the application to put this data into - * a byte stream if needed. The application will not be fed with data - * that is out of sequence. - * - * If the application whishes to send data to the peer, it should put - * its data into the uip_buf. The uip_appdata pointer points to the - * first available byte. The TCP/IP stack will calculate the - * checksums, and fill in the necessary header fields and finally send - * the packet back to the peer. -*/ - -#include "uip.h" -#include "uipopt.h" -#include "uip_arp.h" - -#if !UIP_CONF_IPV6 /* If UIP_CONF_IPV6 is defined, we compile the - uip6.c file instead of this one. Therefore - this #ifndef removes the entire compilation - output of the uip.c file */ - - -#if UIP_CONF_IPV6 -#include "net/uip-neighbor.h" -#endif /* UIP_CONF_IPV6 */ - -#include - -/*---------------------------------------------------------------------------*/ -/* Variable definitions. */ - - -/* The IP address of this host. If it is defined to be fixed (by - setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set - here. Otherwise, the address */ -#if UIP_FIXEDADDR > 0 -const uip_ipaddr_t uip_hostaddr = - { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, UIP_IPADDR3 }; -const uip_ipaddr_t uip_draddr = - { UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3 }; -const uip_ipaddr_t uip_netmask = - { UIP_NETMASK0, UIP_NETMASK1, UIP_NETMASK2, UIP_NETMASK3 }; -#else -uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; -#endif /* UIP_FIXEDADDR */ - -const uip_ipaddr_t uip_broadcast_addr = -#if UIP_CONF_IPV6 - { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; -#else /* UIP_CONF_IPV6 */ - { { 0xff, 0xff, 0xff, 0xff } }; -#endif /* UIP_CONF_IPV6 */ -const uip_ipaddr_t uip_all_zeroes_addr = { { 0x0, /* rest is 0 */ } }; - -#if UIP_FIXEDETHADDR -const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, - UIP_ETHADDR1, - UIP_ETHADDR2, - UIP_ETHADDR3, - UIP_ETHADDR4, - UIP_ETHADDR5}}; -#else -struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; -#endif - -#ifndef UIP_CONF_EXTERNAL_BUFFER -u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains - incoming packets. */ -#endif /* UIP_CONF_EXTERNAL_BUFFER */ - -void *uip_appdata; /* The uip_appdata pointer points to - application data. */ -void *uip_sappdata; /* The uip_appdata pointer points to - the application data which is to - be sent. */ -#if UIP_URGDATA > 0 -void *uip_urgdata; /* The uip_urgdata pointer points to - urgent data (out-of-band data), if - present. */ -u16_t uip_urglen, uip_surglen; -#endif /* UIP_URGDATA > 0 */ - -u16_t uip_len, uip_slen; - /* The uip_len is either 8 or 16 bits, - depending on the maximum packet - size. */ - -u8_t uip_flags; /* The uip_flags variable is used for - communication between the TCP/IP stack - and the application 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. */ -u16_t uip_listenports[UIP_LISTENPORTS]; - /* The uip_listenports list all currently - listening ports. */ -#if UIP_UDP -struct uip_udp_conn *uip_udp_conn; -struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; -#endif /* UIP_UDP */ - -static u16_t ipid; /* Ths ipid variable is an increasing - number that is used for the IP ID - field. */ - -void uip_setipid(u16_t id) { ipid = id; } - -static u8_t iss[4]; /* The iss variable is used for the TCP - initial sequence number. */ - -#if UIP_ACTIVE_OPEN -static u16_t lastport; /* Keeps track of the last port used for - a new connection. */ -#endif /* UIP_ACTIVE_OPEN */ - -/* Temporary variables. */ -u8_t uip_acc32[4]; -static u8_t c, opt; -static u16_t tmp16; - -/* Structures and definitions. */ -#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_CTL 0x3f - -#define TCP_OPT_END 0 /* End of TCP options list */ -#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ -#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ - -#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ - -#define ICMP_ECHO_REPLY 0 -#define ICMP_ECHO 8 - -#define ICMP_DEST_UNREACHABLE 3 -#define ICMP_PORT_UNREACHABLE 3 - -#define ICMP6_ECHO_REPLY 129 -#define ICMP6_ECHO 128 -#define ICMP6_NEIGHBOR_SOLICITATION 135 -#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 - -#define ICMP6_FLAG_S (1 << 6) - -#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 -#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 - - -/* Macros. */ -#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) -#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) - - -#if UIP_STATISTICS == 1 -struct uip_stats uip_stat; -#define UIP_STAT(s) s -#else -#define UIP_STAT(s) -#endif /* UIP_STATISTICS == 1 */ - -#if UIP_LOGGING == 1 -#include -void uip_log(char *msg); -#define UIP_LOG(m) uip_log(m) -#else -#define UIP_LOG(m) -#endif /* UIP_LOGGING == 1 */ - -#if ! UIP_ARCH_ADD32 -void -uip_add32(u8_t *op32, u16_t 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 u16_t -chksum(u16_t sum, const u8_t *data, u16_t len) -{ - u16_t t; - const u8_t *dataptr; - const u8_t *last_byte; - - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - dataptr += 2; - } - - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - /* Return sum in host byte order. */ - return sum; -} -/*---------------------------------------------------------------------------*/ -u16_t -uip_chksum(u16_t *data, u16_t len) -{ - return htons(chksum(0, (u8_t *)data, len)); -} -/*---------------------------------------------------------------------------*/ -#ifndef UIP_ARCH_IPCHKSUM -u16_t -uip_ipchksum(void) -{ - u16_t sum; - - sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); - DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); - return (sum == 0) ? 0xffff : htons(sum); -} -#endif -/*---------------------------------------------------------------------------*/ -static u16_t -upper_layer_chksum(u8_t proto) -{ - u16_t upper_layer_len; - u16_t sum; - -#if UIP_CONF_IPV6 - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); -#else /* UIP_CONF_IPV6 */ - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; -#endif /* UIP_CONF_IPV6 */ - - /* First sum pseudo-header. */ - - /* IP protocol and length fields. This addition cannot carry. */ - sum = upper_layer_len + proto; - /* Sum IP source and destination addresses. */ - sum = chksum(sum, (u8_t *)&BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t)); - - /* Sum TCP header and data. */ - sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], - upper_layer_len); - - return (sum == 0) ? 0xffff : htons(sum); -} -/*---------------------------------------------------------------------------*/ -#if UIP_CONF_IPV6 -u16_t -uip_icmp6chksum(void) -{ - return upper_layer_chksum(UIP_PROTO_ICMP6); - -} -#endif /* UIP_CONF_IPV6 */ -/*---------------------------------------------------------------------------*/ -u16_t -uip_tcpchksum(void) -{ - return upper_layer_chksum(UIP_PROTO_TCP); -} -/*---------------------------------------------------------------------------*/ -#if UIP_UDP_CHECKSUMS -u16_t -uip_udpchksum(void) -{ - return upper_layer_chksum(UIP_PROTO_UDP); -} -#endif /* UIP_UDP_CHECKSUMS */ -#endif /* UIP_ARCH_CHKSUM */ -/*---------------------------------------------------------------------------*/ -void -uip_init(void) -{ - for(c = 0; c < UIP_LISTENPORTS; ++c) { - uip_listenports[c] = 0; - } - for(c = 0; c < UIP_CONNS; ++c) { - uip_conns[c].tcpstateflags = UIP_CLOSED; - } -#if UIP_ACTIVE_OPEN - lastport = 1024; -#endif /* UIP_ACTIVE_OPEN */ - -#if UIP_UDP - for(c = 0; c < UIP_UDP_CONNS; ++c) { - uip_udp_conns[c].lport = 0; - } -#endif /* UIP_UDP */ - - - /* IPv4 initialization. */ -#if UIP_FIXEDADDR == 0 - /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ -#endif /* UIP_FIXEDADDR */ - -} -/*---------------------------------------------------------------------------*/ -#if UIP_ACTIVE_OPEN -struct uip_conn * -uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) -{ - register struct uip_conn *conn, *cconn; - - /* Find an unused local port. */ - again: - ++lastport; - - if(lastport >= 32000) { - lastport = 4096; - } - - /* Check if this port is already in use, and if so try to find - another one. */ - for(c = 0; c < UIP_CONNS; ++c) { - conn = &uip_conns[c]; - if(conn->tcpstateflags != UIP_CLOSED && - conn->lport == htons(lastport)) { - goto again; - } - } - - conn = 0; - for(c = 0; c < UIP_CONNS; ++c) { - cconn = &uip_conns[c]; - if(cconn->tcpstateflags == UIP_CLOSED) { - conn = cconn; - break; - } - if(cconn->tcpstateflags == UIP_TIME_WAIT) { - if(conn == 0 || - cconn->timer > conn->timer) { - conn = cconn; - } - } - } - - if(conn == 0) { - return 0; - } - - 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; -} -#endif /* UIP_ACTIVE_OPEN */ -/*---------------------------------------------------------------------------*/ -#if UIP_UDP -struct uip_udp_conn * -uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport) -{ - register struct uip_udp_conn *conn; - - /* Find an unused local port. */ - again: - ++lastport; - - if(lastport >= 32000) { - lastport = 4096; - } - - for(c = 0; c < UIP_UDP_CONNS; ++c) { - if(uip_udp_conns[c].lport == htons(lastport)) { - goto again; - } - } - - - conn = 0; - for(c = 0; c < UIP_UDP_CONNS; ++c) { - if(uip_udp_conns[c].lport == 0) { - conn = &uip_udp_conns[c]; - break; - } - } - - if(conn == 0) { - return 0; - } - - conn->lport = HTONS(lastport); - 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 /* UIP_UDP */ -/*---------------------------------------------------------------------------*/ -void -uip_unlisten(u16_t port) -{ - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(uip_listenports[c] == port) { - uip_listenports[c] = 0; - return; - } - } -} -/*---------------------------------------------------------------------------*/ -void -uip_listen(u16_t port) -{ - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(uip_listenports[c] == 0) { - uip_listenports[c] = port; - return; - } - } -} -/*---------------------------------------------------------------------------*/ -/* XXX: IP fragment reassembly: not well-tested. */ - -#if UIP_REASSEMBLY && !UIP_CONF_IPV6 -#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) -static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; -static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; -static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, - 0x0f, 0x07, 0x03, 0x01}; -static u16_t uip_reasslen; -static u8_t uip_reassflags; -#define UIP_REASS_FLAG_LASTFRAG 0x01 -static u8_t uip_reasstmr; - -#define IP_MF 0x20 - -static u8_t -uip_reass(void) -{ - u16_t offset, len; - u16_t 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)); - } - - /* 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 in-between 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((BUF->ipoffset[0] & IP_MF) == 0) { - uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; - uip_reasslen = offset + len; - } - - /* 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)] != - (u8_t)~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: - return 0; -} -#endif /* UIP_REASSEMBLY */ -/*---------------------------------------------------------------------------*/ -static void -uip_add_rcv_nxt(u16_t n) -{ - uip_add32(uip_conn->rcv_nxt, n); - uip_conn->rcv_nxt[0] = uip_acc32[0]; - uip_conn->rcv_nxt[1] = uip_acc32[1]; - uip_conn->rcv_nxt[2] = uip_acc32[2]; - uip_conn->rcv_nxt[3] = uip_acc32[3]; -} -/*---------------------------------------------------------------------------*/ -void -uip_process(u8_t flag) -{ - register struct uip_conn *uip_connr = uip_conn; - -#if UIP_UDP - if(flag == UIP_UDP_SEND_CONN) { - goto udp_send; - } -#endif /* UIP_UDP */ - - uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; - - /* Check if we were invoked because of a poll request for a - particular connection. */ - if(flag == UIP_POLL_REQUEST) { - if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && - !uip_outstanding(uip_connr)) { - uip_len = uip_slen = 0; - uip_flags = UIP_POLL; - UIP_APPCALL(); - goto appsend; - } - goto drop; - - /* Check if we were invoked because of the periodic timer firing. */ - } else if(flag == UIP_TIMER) { -#if UIP_REASSEMBLY - if(uip_reasstmr != 0) { - --uip_reasstmr; - } -#endif /* UIP_REASSEMBLY */ - /* Increase the initial sequence number. */ - if(++iss[3] == 0) { - if(++iss[2] == 0) { - if(++iss[1] == 0) { - ++iss[0]; - } - } - } - - /* Reset the length variables. */ - uip_len = 0; - uip_slen = 0; - - /* Check if the connection is in a state in which we simply wait - for the connection to time out. If so, we increase the - connection's timer and remove the connection if it times - out. */ - if(uip_connr->tcpstateflags == UIP_TIME_WAIT || - uip_connr->tcpstateflags == UIP_FIN_WAIT_2) { - ++(uip_connr->timer); - if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { - uip_connr->tcpstateflags = UIP_CLOSED; - } - } else if(uip_connr->tcpstateflags != UIP_CLOSED) { - /* If the connection has outstanding data, we increase the - connection's timer and see if it has reached the RTO value - in which case we retransmit. */ - if(uip_outstanding(uip_connr)) { - if(uip_connr->timer-- == 0) { - if(uip_connr->nrtx == UIP_MAXRTX || - ((uip_connr->tcpstateflags == UIP_SYN_SENT || - uip_connr->tcpstateflags == UIP_SYN_RCVD) && - uip_connr->nrtx == UIP_MAXSYNRTX)) { - uip_connr->tcpstateflags = UIP_CLOSED; - - /* We call UIP_APPCALL() with uip_flags set to - UIP_TIMEDOUT to inform the application that the - connection has timed out. */ - uip_flags = UIP_TIMEDOUT; - UIP_APPCALL(); - - /* We also send a reset packet to the remote host. */ - BUF->flags = TCP_RST | TCP_ACK; - goto tcp_send_nodata; - } - - /* Exponential back-off. */ - uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? - 4: - uip_connr->nrtx); - ++(uip_connr->nrtx); - - /* Ok, so we need to retransmit. We do this differently - depending on which state we are in. In ESTABLISHED, we - call upon the application so that it may prepare the - data for the retransmit. In SYN_RCVD, we resend the - SYNACK that we sent earlier and in LAST_ACK we have to - retransmit our FINACK. */ - UIP_STAT(++uip_stat.tcp.rexmit); - switch(uip_connr->tcpstateflags & UIP_TS_MASK) { - case UIP_SYN_RCVD: - /* In the SYN_RCVD state, we should retransmit our - SYNACK. */ - goto tcp_send_synack; - -#if UIP_ACTIVE_OPEN - case UIP_SYN_SENT: - /* In the SYN_SENT state, we retransmit out SYN. */ - BUF->flags = 0; - goto tcp_send_syn; -#endif /* UIP_ACTIVE_OPEN */ - - case UIP_ESTABLISHED: - /* In the ESTABLISHED state, we call upon the application - to do the actual retransmit after which we jump into - the code for sending out the packet (the apprexmit - label). */ - uip_flags = UIP_REXMIT; - UIP_APPCALL(); - goto apprexmit; - - case UIP_FIN_WAIT_1: - case UIP_CLOSING: - case UIP_LAST_ACK: - /* In all these states we should retransmit a FINACK. */ - goto tcp_send_finack; - - } - } - } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { - /* If there was no need for a retransmission, we poll the - application for new data. */ - uip_len = uip_slen = 0; - uip_flags = UIP_POLL; - UIP_APPCALL(); - goto appsend; - } - } - goto drop; - } -#if UIP_UDP - if(flag == UIP_UDP_TIMER) { - if(uip_udp_conn->lport != 0) { - uip_conn = NULL; - uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; - uip_len = uip_slen = 0; - uip_flags = UIP_POLL; - UIP_UDP_APPCALL(); - goto udp_send; - } else { - goto drop; - } - } -#endif - - /* This is where the input processing starts. */ - UIP_STAT(++uip_stat.ip.recv); - - /* Start of IP input header processing code. */ - -#if UIP_CONF_IPV6 - /* Check validity of the IP header. */ - if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.vhlerr); - UIP_LOG("ipv6: invalid version."); - goto drop; - } -#else /* UIP_CONF_IPV6 */ - /* Check validity of the IP header. */ - if(BUF->vhl != 0x45) { /* IP version and header length. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.vhlerr); - UIP_LOG("ip: invalid version or header length."); - goto drop; - } -#endif /* UIP_CONF_IPV6 */ - - /* Check the size of the packet. If the size reported to us in - uip_len is smaller the size reported in the IP header, we assume - that the packet has been corrupted in transit. If the size of - uip_len is larger than the size reported in the IP packet header, - the packet has been padded and we set uip_len to the correct - value.. */ - - if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { - uip_len = (BUF->len[0] << 8) + BUF->len[1]; -#if UIP_CONF_IPV6 - uip_len += 40; /* The length reported in the IPv6 header is the - length of the payload that follows the - header. However, uIP uses the uip_len variable - for holding the size of the entire packet, - including the IP header. For IPv4 this is not a - problem as the length field in the IPv4 header - contains the length of the entire packet. But - for IPv6 we need to add the size of the IPv6 - header (40 bytes). */ -#endif /* UIP_CONF_IPV6 */ - } else { - UIP_LOG("ip: packet shorter than reported in IP header."); - goto drop; - } - -#if !UIP_CONF_IPV6 - /* Check the fragment flag. */ - if((BUF->ipoffset[0] & 0x3f) != 0 || - BUF->ipoffset[1] != 0) { -#if UIP_REASSEMBLY - uip_len = uip_reass(); - if(uip_len == 0) { - goto drop; - } -#else /* UIP_REASSEMBLY */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.fragerr); - UIP_LOG("ip: fragment dropped."); - goto drop; -#endif /* UIP_REASSEMBLY */ - } -#endif /* UIP_CONF_IPV6 */ - - if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) { - /* If we are configured to use ping IP address configuration and - hasn't been assigned an IP address yet, we accept all ICMP - packets. */ -#if UIP_PINGADDRCONF && !UIP_CONF_IPV6 - if(BUF->proto == UIP_PROTO_ICMP) { - UIP_LOG("ip: possible ping config packet received."); - goto icmp_input; - } else { - UIP_LOG("ip: packet dropped since no address assigned."); - goto drop; - } -#endif /* UIP_PINGADDRCONF */ - - } else { - /* If IP broadcast support is configured, we check for a broadcast - UDP packet, which may be destined to us. */ -#if UIP_BROADCAST - DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); - if(BUF->proto == UIP_PROTO_UDP && - uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) - { - if (uip_ipaddr_cmp(&BUF->srcipaddr, &uip_all_zeroes_addr)) - uip_ipaddr_copy(&BUF->srcipaddr, &uip_broadcast_addr); - - goto udp_input; - } -#endif /* UIP_BROADCAST */ - - /* Check if the packet is destined for our IP address. */ -#if !UIP_CONF_IPV6 - if(!uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) { - UIP_STAT(++uip_stat.ip.drop); - goto drop; - } -#else /* UIP_CONF_IPV6 */ - /* For IPv6, packet reception is a little trickier as we need to - make sure that we listen to certain multicast addresses (all - hosts multicast address, and the solicited-node multicast - address) as well. However, we will cheat here and accept all - multicast packets that are sent to the ff02::/16 addresses. */ - if(!uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr) && - BUF->destipaddr.u16[0] != HTONS(0xff02)) { - UIP_STAT(++uip_stat.ip.drop); - goto drop; - } -#endif /* UIP_CONF_IPV6 */ - } - -#if !UIP_CONF_IPV6 - if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header - checksum. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.chkerr); - UIP_LOG("ip: bad checksum."); - goto drop; - } -#endif /* UIP_CONF_IPV6 */ - - if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, - proceed with TCP input - processing. */ - goto tcp_input; - } - -#if UIP_UDP - if(BUF->proto == UIP_PROTO_UDP) { - goto udp_input; - } -#endif /* UIP_UDP */ - -#if !UIP_CONF_IPV6 - /* ICMPv4 processing code follows. */ - if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from - here. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.protoerr); - UIP_LOG("ip: neither tcp nor icmp."); - goto drop; - } - -#if UIP_PINGADDRCONF - icmp_input: -#endif /* UIP_PINGADDRCONF */ - UIP_STAT(++uip_stat.icmp.recv); - - /* ICMP echo (i.e., ping) processing. This is simple, we only change - the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP - checksum before we return the packet. */ - if(ICMPBUF->type != ICMP_ECHO) { - UIP_STAT(++uip_stat.icmp.drop); - UIP_STAT(++uip_stat.icmp.typeerr); - UIP_LOG("icmp: not icmp echo."); - goto drop; - } - - /* If we are configured to use ping IP address assignment, we use - the destination IP address of this ping packet and assign it to - yourself. */ -#if UIP_PINGADDRCONF - if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) { - uip_hostaddr = BUF->destipaddr; - } -#endif /* UIP_PINGADDRCONF */ - - ICMPBUF->type = ICMP_ECHO_REPLY; - - if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { - ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; - } else { - ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); - } - - /* Swap IP addresses. */ - uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); - uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); - - UIP_STAT(++uip_stat.icmp.sent); - BUF->ttl = UIP_TTL; - goto ip_send_nolen; - - /* End of IPv4 input header processing code. */ -#else /* !UIP_CONF_IPV6 */ - - /* This is IPv6 ICMPv6 processing code. */ - DEBUG_PRINTF("icmp6_input: length %d\n", uip_len); - - if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from - here. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.protoerr); - UIP_LOG("ip: neither tcp nor icmp6."); - goto drop; - } - - UIP_STAT(++uip_stat.icmp.recv); - - /* If we get a neighbor solicitation for our address we should send - a neighbor advertisement message back. */ - if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) { - if(uip_ipaddr_cmp(&ICMPBUF->icmp6data, &uip_hostaddr)) { - - if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { - /* Save the sender's address in our neighbor list. */ - uip_neighbor_add(&ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); - } - - /* We should now send a neighbor advertisement back to where the - neighbor solicitation came from. */ - ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; - ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ - - ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; - - uip_ipaddr_copy(&ICMPBUF->destipaddr, &ICMPBUF->srcipaddr); - uip_ipaddr_copy(&ICMPBUF->srcipaddr, &uip_hostaddr); - ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; - ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ - memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); - ICMPBUF->icmpchksum = 0; - ICMPBUF->icmpchksum = ~uip_icmp6chksum(); - - goto send; - - } - goto drop; - } else if(ICMPBUF->type == ICMP6_ECHO) { - /* ICMP echo (i.e., ping) processing. This is simple, we only - change the ICMP type from ECHO to ECHO_REPLY and update the - ICMP checksum before we return the packet. */ - - ICMPBUF->type = ICMP6_ECHO_REPLY; - - uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); - uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); - ICMPBUF->icmpchksum = 0; - ICMPBUF->icmpchksum = ~uip_icmp6chksum(); - - UIP_STAT(++uip_stat.icmp.sent); - goto send; - } else { - DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type); - UIP_STAT(++uip_stat.icmp.drop); - UIP_STAT(++uip_stat.icmp.typeerr); - UIP_LOG("icmp: unknown ICMP message."); - goto drop; - } - - /* End of IPv6 ICMP processing. */ - -#endif /* !UIP_CONF_IPV6 */ - -#if UIP_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. */ -#if UIP_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) { - UIP_STAT(++uip_stat.udp.drop); - UIP_STAT(++uip_stat.udp.chkerr); - UIP_LOG("udp: bad checksum."); - goto drop; - } -#else /* UIP_UDP_CHECKSUMS */ - uip_len = uip_len - UIP_IPUDPH_LEN; -#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) { - /* 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 - destination port number in the received packet. If the two port - numbers match, the remote port number is checked if the - connection is bound to a remote port. Finally, if the - connection is bound to a remote IP address, the source IP - address of the packet is checked. */ - 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, &uip_all_zeroes_addr) || - uip_ipaddr_cmp(&uip_udp_conn->ripaddr, &uip_broadcast_addr) || - uip_ipaddr_cmp(&BUF->srcipaddr, &uip_udp_conn->ripaddr))) { - goto udp_found; - } - } - UIP_LOG("udp: no matching connection found"); -#if UIP_CONF_ICMP_DEST_UNREACH && !UIP_CONF_IPV6 - /* Copy fields from packet header into payload of this ICMP packet. */ - memcpy(&(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8); - - /* Set the ICMP type and code. */ - ICMPBUF->type = ICMP_DEST_UNREACHABLE; - ICMPBUF->icode = ICMP_PORT_UNREACHABLE; - - /* Calculate the ICMP checksum. */ - ICMPBUF->icmpchksum = 0; - ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36); - - /* Set the IP destination address to be the source address of the - original packet. */ - uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); - - /* Set our IP address as the source address. */ - uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); - - /* The size of the ICMP destination unreachable packet is 36 + the - size of the IP header (20) = 56. */ - uip_len = 36 + UIP_IPH_LEN; - ICMPBUF->len[0] = 0; - ICMPBUF->len[1] = (u8_t)uip_len; - ICMPBUF->ttl = UIP_TTL; - ICMPBUF->proto = UIP_PROTO_ICMP; - - goto ip_send_nolen; -#else /* UIP_CONF_ICMP_DEST_UNREACH */ - goto drop; -#endif /* UIP_CONF_ICMP_DEST_UNREACH */ - - udp_found: - uip_conn = NULL; - uip_flags = UIP_NEWDATA; - uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; - uip_slen = 0; - UIP_UDP_APPCALL(); - - udp_send: - if(uip_slen == 0) { - goto drop; - } - uip_len = uip_slen + UIP_IPUDPH_LEN; - -#if UIP_CONF_IPV6 - /* For IPv6, the IP length field does not include the IPv6 IP header - length. */ - BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); -#else /* UIP_CONF_IPV6 */ - BUF->len[0] = (uip_len >> 8); - BUF->len[1] = (uip_len & 0xff); -#endif /* UIP_CONF_IPV6 */ - - BUF->ttl = uip_udp_conn->ttl; - BUF->proto = UIP_PROTO_UDP; - - UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); - UDPBUF->udpchksum = 0; - - BUF->srcport = uip_udp_conn->lport; - BUF->destport = uip_udp_conn->rport; - - uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); - uip_ipaddr_copy(&BUF->destipaddr, &uip_udp_conn->ripaddr); - - uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; - -#if UIP_UDP_CHECKSUMS - /* Calculate UDP checksum. */ - UDPBUF->udpchksum = ~(uip_udpchksum()); - if(UDPBUF->udpchksum == 0) { - UDPBUF->udpchksum = 0xffff; - } -#endif /* UIP_UDP_CHECKSUMS */ - - goto ip_send_nolen; -#endif /* UIP_UDP */ - - /* TCP input processing. */ - tcp_input: - UIP_STAT(++uip_stat.tcp.recv); - - /* Start of TCP input header processing code. */ - - 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) { - 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; - } - } - - /* 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. */ - if((BUF->flags & TCP_CTL) != TCP_SYN) { - goto reset; - } - - tmp16 = BUF->destport; - /* Next, check listening connections. */ - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(tmp16 == uip_listenports[c]) { - goto found_listen; - } - } - - /* No matching connection found, so we send a RST packet. */ - UIP_STAT(++uip_stat.tcp.synrst); - - reset: - /* We do not send resets in response to resets. */ - if(BUF->flags & TCP_RST) { - goto drop; - } - - UIP_STAT(++uip_stat.tcp.rst); - - BUF->flags = TCP_RST | TCP_ACK; - uip_len = UIP_IPTCPH_LEN; - BUF->tcpoffset = 5 << 4; - - /* Flip the seqno and ackno fields in the TCP header. */ - c = BUF->seqno[3]; - BUF->seqno[3] = BUF->ackno[3]; - BUF->ackno[3] = c; - - c = BUF->seqno[2]; - BUF->seqno[2] = BUF->ackno[2]; - BUF->ackno[2] = c; - - c = BUF->seqno[1]; - BUF->seqno[1] = BUF->ackno[1]; - BUF->ackno[1] = c; - - c = BUF->seqno[0]; - BUF->seqno[0] = BUF->ackno[0]; - BUF->ackno[0] = c; - - /* We also have to increase the sequence number we are - acknowledging. If the least significant byte overflowed, we need - to propagate the carry to the other bytes as well. */ - if(++BUF->ackno[3] == 0) { - if(++BUF->ackno[2] == 0) { - if(++BUF->ackno[1] == 0) { - ++BUF->ackno[0]; - } - } - } - - /* Swap port numbers. */ - tmp16 = BUF->srcport; - BUF->srcport = BUF->destport; - BUF->destport = tmp16; - - /* Swap IP addresses. */ - uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); - uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); - - /* And send out the RST packet! */ - 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 available. 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]; - } - } - } - - if(uip_connr == 0) { - /* 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. */ - UIP_STAT(++uip_stat.tcp.syndrop); - 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->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->len = 1; - - /* rcv_nxt should be the seqno from the incoming packet + 1. */ - uip_connr->rcv_nxt[3] = BUF->seqno[3]; - uip_connr->rcv_nxt[2] = BUF->seqno[2]; - uip_connr->rcv_nxt[1] = BUF->seqno[1]; - uip_connr->rcv_nxt[0] = BUF->seqno[0]; - uip_add_rcv_nxt(1); - - /* Parse the TCP MSS option, if present. */ - if((BUF->tcpoffset & 0xf0) > 0x50) { - for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; - if(opt == TCP_OPT_END) { - /* End of options. */ - break; - } else if(opt == TCP_OPT_NOOP) { - ++c; - /* NOP option. */ - } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { - /* An MSS option with the right option length. */ - tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; - uip_connr->initialmss = uip_connr->mss = - tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; - - /* And we are done processing options. */ - break; - } else { - /* All other options have a length field, so that we easily - can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { - /* If the length field is zero, the options are malformed - and we don't process them further. */ - break; - } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; - } - } - } - - /* Our response will be a SYNACK. */ -#if UIP_ACTIVE_OPEN - tcp_send_synack: - BUF->flags = TCP_ACK; - - tcp_send_syn: - BUF->flags |= TCP_SYN; -#else /* UIP_ACTIVE_OPEN */ - tcp_send_synack: - BUF->flags = TCP_SYN | TCP_ACK; -#endif /* UIP_ACTIVE_OPEN */ - - /* We send out the TCP Maximum Segment Size option with our - SYNACK. */ - BUF->optdata[0] = TCP_OPT_MSS; - BUF->optdata[1] = TCP_OPT_MSS_LEN; - BUF->optdata[2] = (UIP_TCP_MSS) / 256; - BUF->optdata[3] = (UIP_TCP_MSS) & 255; - uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; - BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; - goto tcp_send; - - /* This label will be jumped to if we found an active connection. */ - found: - uip_conn = uip_connr; - uip_flags = 0; - /* We do a very naive form of TCP reset processing; we just accept - any RST and kill our connection. We should in fact check if the - sequence number of this reset is within our advertised window - before we accept the reset. */ - if(BUF->flags & TCP_RST) { - uip_connr->tcpstateflags = UIP_CLOSED; - UIP_LOG("tcp: got reset, aborting connection."); - uip_flags = UIP_ABORT; - UIP_APPCALL(); -