UIPEthernet library for Arduino IDE, Eclipse with arduino plugin and MBED/SMeshStudio (AVR,STM32F,ESP8266,Intel ARC32,Nordic nRF51,Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip. Compatible with Wiznet W5100 Ethernet library API. Compiled and tested on Nucleo-F302R8. Master repository is: https://github.com/UIPEthernet/UIPEthernet/

Committer:
cassyarduino
Date:
Tue Jan 23 15:08:43 2018 +0100
Revision:
39:deeb00b81cc9
Parent:
36:689bcc358067
Release: 2.0.4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cassyarduino 0:e3fb1267e3c3 1 #define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/
cassyarduino 0:e3fb1267e3c3 2
cassyarduino 0:e3fb1267e3c3 3 /**
cassyarduino 0:e3fb1267e3c3 4 * \defgroup uip The uIP TCP/IP stack
cassyarduino 0:e3fb1267e3c3 5 * @{
cassyarduino 0:e3fb1267e3c3 6 *
cassyarduino 0:e3fb1267e3c3 7 * uIP is an implementation of the TCP/IP protocol stack intended for
cassyarduino 0:e3fb1267e3c3 8 * small 8-bit and 16-bit microcontrollers.
cassyarduino 0:e3fb1267e3c3 9 *
cassyarduino 0:e3fb1267e3c3 10 * uIP provides the necessary protocols for Internet communication,
cassyarduino 0:e3fb1267e3c3 11 * with a very small code footprint and RAM requirements - the uIP
cassyarduino 0:e3fb1267e3c3 12 * code size is on the order of a few kilobytes and RAM usage is on
cassyarduino 0:e3fb1267e3c3 13 * the order of a few hundred bytes.
cassyarduino 0:e3fb1267e3c3 14 */
cassyarduino 0:e3fb1267e3c3 15
cassyarduino 0:e3fb1267e3c3 16 /**
cassyarduino 0:e3fb1267e3c3 17 * \file
cassyarduino 0:e3fb1267e3c3 18 * The uIP TCP/IP stack code.
cassyarduino 0:e3fb1267e3c3 19 * \author Adam Dunkels <adam@dunkels.com>
cassyarduino 0:e3fb1267e3c3 20 */
cassyarduino 0:e3fb1267e3c3 21
cassyarduino 0:e3fb1267e3c3 22 /*
cassyarduino 0:e3fb1267e3c3 23 * Copyright (c) 2001-2003, Adam Dunkels.
cassyarduino 0:e3fb1267e3c3 24 * All rights reserved.
cassyarduino 0:e3fb1267e3c3 25 *
cassyarduino 0:e3fb1267e3c3 26 * Redistribution and use in source and binary forms, with or without
cassyarduino 0:e3fb1267e3c3 27 * modification, are permitted provided that the following conditions
cassyarduino 0:e3fb1267e3c3 28 * are met:
cassyarduino 0:e3fb1267e3c3 29 * 1. Redistributions of source code must retain the above copyright
cassyarduino 0:e3fb1267e3c3 30 * notice, this list of conditions and the following disclaimer.
cassyarduino 0:e3fb1267e3c3 31 * 2. Redistributions in binary form must reproduce the above copyright
cassyarduino 0:e3fb1267e3c3 32 * notice, this list of conditions and the following disclaimer in the
cassyarduino 0:e3fb1267e3c3 33 * documentation and/or other materials provided with the distribution.
cassyarduino 0:e3fb1267e3c3 34 * 3. The name of the author may not be used to endorse or promote
cassyarduino 0:e3fb1267e3c3 35 * products derived from this software without specific prior
cassyarduino 0:e3fb1267e3c3 36 * written permission.
cassyarduino 0:e3fb1267e3c3 37 *
cassyarduino 0:e3fb1267e3c3 38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
cassyarduino 0:e3fb1267e3c3 39 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
cassyarduino 0:e3fb1267e3c3 40 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
cassyarduino 0:e3fb1267e3c3 41 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
cassyarduino 0:e3fb1267e3c3 42 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
cassyarduino 0:e3fb1267e3c3 43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
cassyarduino 0:e3fb1267e3c3 44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
cassyarduino 0:e3fb1267e3c3 45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
cassyarduino 0:e3fb1267e3c3 46 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
cassyarduino 0:e3fb1267e3c3 47 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
cassyarduino 0:e3fb1267e3c3 48 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cassyarduino 0:e3fb1267e3c3 49 *
cassyarduino 0:e3fb1267e3c3 50 * This file is part of the uIP TCP/IP stack.
cassyarduino 0:e3fb1267e3c3 51 *
cassyarduino 0:e3fb1267e3c3 52 * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
cassyarduino 0:e3fb1267e3c3 53 *
cassyarduino 0:e3fb1267e3c3 54 */
cassyarduino 0:e3fb1267e3c3 55
cassyarduino 0:e3fb1267e3c3 56 /*
cassyarduino 0:e3fb1267e3c3 57 * uIP is a small implementation of the IP, UDP and TCP protocols (as
cassyarduino 0:e3fb1267e3c3 58 * well as some basic ICMP stuff). The implementation couples the IP,
cassyarduino 0:e3fb1267e3c3 59 * UDP, TCP and the application layers very tightly. To keep the size
cassyarduino 0:e3fb1267e3c3 60 * of the compiled code down, this code frequently uses the goto
cassyarduino 0:e3fb1267e3c3 61 * statement. While it would be possible to break the uip_process()
cassyarduino 0:e3fb1267e3c3 62 * function into many smaller functions, this would increase the code
cassyarduino 0:e3fb1267e3c3 63 * size because of the overhead of parameter passing and the fact that
cassyarduino 0:e3fb1267e3c3 64 * the optimier would not be as efficient.
cassyarduino 0:e3fb1267e3c3 65 *
cassyarduino 0:e3fb1267e3c3 66 * The principle is that we have a small buffer, called the uip_buf,
cassyarduino 0:e3fb1267e3c3 67 * in which the device driver puts an incoming packet. The TCP/IP
cassyarduino 0:e3fb1267e3c3 68 * stack parses the headers in the packet, and calls the
cassyarduino 0:e3fb1267e3c3 69 * application. If the remote host has sent data to the application,
cassyarduino 0:e3fb1267e3c3 70 * this data is present in the uip_buf and the application read the
cassyarduino 0:e3fb1267e3c3 71 * data from there. It is up to the application to put this data into
cassyarduino 0:e3fb1267e3c3 72 * a byte stream if needed. The application will not be fed with data
cassyarduino 0:e3fb1267e3c3 73 * that is out of sequence.
cassyarduino 0:e3fb1267e3c3 74 *
cassyarduino 0:e3fb1267e3c3 75 * If the application whishes to send data to the peer, it should put
cassyarduino 0:e3fb1267e3c3 76 * its data into the uip_buf. The uip_appdata pointer points to the
cassyarduino 0:e3fb1267e3c3 77 * first available byte. The TCP/IP stack will calculate the
cassyarduino 0:e3fb1267e3c3 78 * checksums, and fill in the necessary header fields and finally send
cassyarduino 0:e3fb1267e3c3 79 * the packet back to the peer.
cassyarduino 0:e3fb1267e3c3 80 */
cassyarduino 0:e3fb1267e3c3 81
cassyarduino 0:e3fb1267e3c3 82 #include "uip.h"
cassyarduino 0:e3fb1267e3c3 83 #include "uipopt.h"
cassyarduino 0:e3fb1267e3c3 84 #include "uip_arch.h"
cassyarduino 0:e3fb1267e3c3 85
cassyarduino 0:e3fb1267e3c3 86 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 87 #include "uip-neighbor.h"
cassyarduino 0:e3fb1267e3c3 88 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 89
cassyarduino 0:e3fb1267e3c3 90 #include <string.h>
cassyarduino 0:e3fb1267e3c3 91
cassyarduino 0:e3fb1267e3c3 92 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 93 /* Variable definitions. */
cassyarduino 0:e3fb1267e3c3 94
cassyarduino 0:e3fb1267e3c3 95
cassyarduino 0:e3fb1267e3c3 96 /* The IP address of this host. If it is defined to be fixed (by
cassyarduino 0:e3fb1267e3c3 97 setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
cassyarduino 0:e3fb1267e3c3 98 here. Otherwise, the address */
cassyarduino 0:e3fb1267e3c3 99 #if UIP_FIXEDADDR > 0
cassyarduino 0:e3fb1267e3c3 100 const uip_ipaddr_t uip_hostaddr =
cassyarduino 0:e3fb1267e3c3 101 {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
cassyarduino 0:e3fb1267e3c3 102 HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
cassyarduino 0:e3fb1267e3c3 103 const uip_ipaddr_t uip_draddr =
cassyarduino 0:e3fb1267e3c3 104 {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
cassyarduino 0:e3fb1267e3c3 105 HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
cassyarduino 0:e3fb1267e3c3 106 const uip_ipaddr_t uip_netmask =
cassyarduino 0:e3fb1267e3c3 107 {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
cassyarduino 0:e3fb1267e3c3 108 HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
cassyarduino 0:e3fb1267e3c3 109 #else
cassyarduino 0:e3fb1267e3c3 110 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
cassyarduino 0:e3fb1267e3c3 111 #endif /* UIP_FIXEDADDR */
cassyarduino 0:e3fb1267e3c3 112
cassyarduino 0:e3fb1267e3c3 113 static const uip_ipaddr_t all_ones_addr =
cassyarduino 0:e3fb1267e3c3 114 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 115 {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
cassyarduino 0:e3fb1267e3c3 116 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 117 {0xffff,0xffff};
cassyarduino 0:e3fb1267e3c3 118 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 119 static const uip_ipaddr_t all_zeroes_addr =
cassyarduino 0:e3fb1267e3c3 120 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 121 {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
cassyarduino 0:e3fb1267e3c3 122 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 123 {0x0000,0x0000};
cassyarduino 0:e3fb1267e3c3 124 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 125
cassyarduino 0:e3fb1267e3c3 126
cassyarduino 0:e3fb1267e3c3 127 #if UIP_FIXEDETHADDR
cassyarduino 0:e3fb1267e3c3 128 const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
cassyarduino 0:e3fb1267e3c3 129 UIP_ETHADDR1,
cassyarduino 0:e3fb1267e3c3 130 UIP_ETHADDR2,
cassyarduino 0:e3fb1267e3c3 131 UIP_ETHADDR3,
cassyarduino 0:e3fb1267e3c3 132 UIP_ETHADDR4,
cassyarduino 0:e3fb1267e3c3 133 UIP_ETHADDR5}};
cassyarduino 0:e3fb1267e3c3 134 #else
cassyarduino 0:e3fb1267e3c3 135 struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
cassyarduino 0:e3fb1267e3c3 136 #endif
cassyarduino 0:e3fb1267e3c3 137
cassyarduino 0:e3fb1267e3c3 138 #ifndef UIP_CONF_EXTERNAL_BUFFER
cassyarduino 0:e3fb1267e3c3 139 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
cassyarduino 0:e3fb1267e3c3 140 incoming packets. */
cassyarduino 0:e3fb1267e3c3 141 #endif /* UIP_CONF_EXTERNAL_BUFFER */
cassyarduino 0:e3fb1267e3c3 142
cassyarduino 0:e3fb1267e3c3 143 void *uip_appdata; /* The uip_appdata pointer points to
cassyarduino 0:e3fb1267e3c3 144 application data. */
cassyarduino 0:e3fb1267e3c3 145 void *uip_sappdata; /* The uip_appdata pointer points to
cassyarduino 0:e3fb1267e3c3 146 the application data which is to
cassyarduino 0:e3fb1267e3c3 147 be sent. */
cassyarduino 0:e3fb1267e3c3 148 #if UIP_URGDATA > 0
cassyarduino 0:e3fb1267e3c3 149 void *uip_urgdata; /* The uip_urgdata pointer points to
cassyarduino 0:e3fb1267e3c3 150 urgent data (out-of-band data), if
cassyarduino 0:e3fb1267e3c3 151 present. */
cassyarduino 0:e3fb1267e3c3 152 u16_t uip_urglen, uip_surglen;
cassyarduino 0:e3fb1267e3c3 153 #endif /* UIP_URGDATA > 0 */
cassyarduino 0:e3fb1267e3c3 154
cassyarduino 0:e3fb1267e3c3 155 u16_t uip_len, uip_slen;
cassyarduino 0:e3fb1267e3c3 156 /* The uip_len is either 8 or 16 bits,
cassyarduino 0:e3fb1267e3c3 157 depending on the maximum packet
cassyarduino 0:e3fb1267e3c3 158 size. */
cassyarduino 0:e3fb1267e3c3 159
cassyarduino 0:e3fb1267e3c3 160 u8_t uip_flags; /* The uip_flags variable is used for
cassyarduino 0:e3fb1267e3c3 161 communication between the TCP/IP stack
cassyarduino 0:e3fb1267e3c3 162 and the application program. */
cassyarduino 0:e3fb1267e3c3 163 struct uip_conn *uip_conn; /* uip_conn always points to the current
cassyarduino 0:e3fb1267e3c3 164 connection. */
cassyarduino 0:e3fb1267e3c3 165
cassyarduino 0:e3fb1267e3c3 166 struct uip_conn uip_conns[UIP_CONNS];
cassyarduino 0:e3fb1267e3c3 167 /* The uip_conns array holds all TCP
cassyarduino 0:e3fb1267e3c3 168 connections. */
cassyarduino 0:e3fb1267e3c3 169 u16_t uip_listenports[UIP_LISTENPORTS];
cassyarduino 0:e3fb1267e3c3 170 /* The uip_listenports list all currently
cassyarduino 0:e3fb1267e3c3 171 listning ports. */
cassyarduino 0:e3fb1267e3c3 172 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 173 struct uip_udp_conn *uip_udp_conn;
cassyarduino 0:e3fb1267e3c3 174 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
cassyarduino 0:e3fb1267e3c3 175 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 176
cassyarduino 0:e3fb1267e3c3 177 static u16_t ipid; /* Ths ipid variable is an increasing
cassyarduino 0:e3fb1267e3c3 178 number that is used for the IP ID
cassyarduino 0:e3fb1267e3c3 179 field. */
cassyarduino 0:e3fb1267e3c3 180
cassyarduino 0:e3fb1267e3c3 181 void uip_setipid(u16_t id) { ipid = id; }
cassyarduino 0:e3fb1267e3c3 182
cassyarduino 0:e3fb1267e3c3 183 static u8_t iss[4]; /* The iss variable is used for the TCP
cassyarduino 0:e3fb1267e3c3 184 initial sequence number. */
cassyarduino 0:e3fb1267e3c3 185
cassyarduino 0:e3fb1267e3c3 186 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 187 static u16_t lastport; /* Keeps track of the last port used for
cassyarduino 0:e3fb1267e3c3 188 a new connection. */
cassyarduino 0:e3fb1267e3c3 189 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 190
cassyarduino 0:e3fb1267e3c3 191 /* Temporary variables. */
cassyarduino 0:e3fb1267e3c3 192 u8_t uip_acc32[4];
cassyarduino 0:e3fb1267e3c3 193 static u8_t c, opt;
cassyarduino 0:e3fb1267e3c3 194 static u16_t tmp16;
cassyarduino 0:e3fb1267e3c3 195
cassyarduino 0:e3fb1267e3c3 196 /* Structures and definitions. */
cassyarduino 0:e3fb1267e3c3 197 #define TCP_FIN 0x01
cassyarduino 0:e3fb1267e3c3 198 #define TCP_SYN 0x02
cassyarduino 0:e3fb1267e3c3 199 #define TCP_RST 0x04
cassyarduino 0:e3fb1267e3c3 200 #define TCP_PSH 0x08
cassyarduino 0:e3fb1267e3c3 201 #define TCP_ACK 0x10
cassyarduino 0:e3fb1267e3c3 202 #define TCP_URG 0x20
cassyarduino 0:e3fb1267e3c3 203 #define TCP_CTL 0x3f
cassyarduino 0:e3fb1267e3c3 204
cassyarduino 0:e3fb1267e3c3 205 #define TCP_OPT_END 0 /* End of TCP options list */
cassyarduino 0:e3fb1267e3c3 206 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
cassyarduino 0:e3fb1267e3c3 207 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
cassyarduino 0:e3fb1267e3c3 208
cassyarduino 0:e3fb1267e3c3 209 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
cassyarduino 0:e3fb1267e3c3 210
cassyarduino 0:e3fb1267e3c3 211 #define ICMP_ECHO_REPLY 0
cassyarduino 0:e3fb1267e3c3 212 #define ICMP_ECHO 8
cassyarduino 0:e3fb1267e3c3 213
cassyarduino 0:e3fb1267e3c3 214 #define ICMP6_ECHO_REPLY 129
cassyarduino 0:e3fb1267e3c3 215 #define ICMP6_ECHO 128
cassyarduino 0:e3fb1267e3c3 216 #define ICMP6_NEIGHBOR_SOLICITATION 135
cassyarduino 0:e3fb1267e3c3 217 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
cassyarduino 0:e3fb1267e3c3 218
cassyarduino 0:e3fb1267e3c3 219 #define ICMP6_FLAG_S (1 << 6)
cassyarduino 0:e3fb1267e3c3 220
cassyarduino 0:e3fb1267e3c3 221 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
cassyarduino 0:e3fb1267e3c3 222 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
cassyarduino 0:e3fb1267e3c3 223
cassyarduino 0:e3fb1267e3c3 224
cassyarduino 0:e3fb1267e3c3 225 /* Macros. */
cassyarduino 0:e3fb1267e3c3 226 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
cassyarduino 0:e3fb1267e3c3 227 #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
cassyarduino 0:e3fb1267e3c3 228 #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
cassyarduino 0:e3fb1267e3c3 229 #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
cassyarduino 0:e3fb1267e3c3 230
cassyarduino 0:e3fb1267e3c3 231
cassyarduino 0:e3fb1267e3c3 232 #if UIP_STATISTICS == 1
cassyarduino 0:e3fb1267e3c3 233 struct uip_stats uip_stat;
cassyarduino 0:e3fb1267e3c3 234 #define UIP_STAT(s) s
cassyarduino 0:e3fb1267e3c3 235 #else
cassyarduino 0:e3fb1267e3c3 236 #define UIP_STAT(s)
cassyarduino 0:e3fb1267e3c3 237 #endif /* UIP_STATISTICS == 1 */
cassyarduino 0:e3fb1267e3c3 238
cassyarduino 0:e3fb1267e3c3 239 #if UIP_LOGGING == 1
cassyarduino 0:e3fb1267e3c3 240 #include <stdio.h>
cassyarduino 0:e3fb1267e3c3 241 void uip_log(char *msg);
cassyarduino 0:e3fb1267e3c3 242 #define UIP_LOG(m) uip_log(m)
cassyarduino 0:e3fb1267e3c3 243 #else
cassyarduino 0:e3fb1267e3c3 244 #define UIP_LOG(m)
cassyarduino 0:e3fb1267e3c3 245 #endif /* UIP_LOGGING == 1 */
cassyarduino 0:e3fb1267e3c3 246
cassyarduino 0:e3fb1267e3c3 247 #if ! UIP_ARCH_ADD32
cassyarduino 0:e3fb1267e3c3 248 void
cassyarduino 0:e3fb1267e3c3 249 uip_add32(u8_t *op32, u16_t op16)
cassyarduino 0:e3fb1267e3c3 250 {
cassyarduino 0:e3fb1267e3c3 251 uip_acc32[3] = op32[3] + (op16 & 0xff);
cassyarduino 0:e3fb1267e3c3 252 uip_acc32[2] = op32[2] + (op16 >> 8);
cassyarduino 0:e3fb1267e3c3 253 uip_acc32[1] = op32[1];
cassyarduino 0:e3fb1267e3c3 254 uip_acc32[0] = op32[0];
cassyarduino 0:e3fb1267e3c3 255
cassyarduino 0:e3fb1267e3c3 256 if(uip_acc32[2] < (op16 >> 8)) {
cassyarduino 0:e3fb1267e3c3 257 ++uip_acc32[1];
cassyarduino 0:e3fb1267e3c3 258 if(uip_acc32[1] == 0) {
cassyarduino 0:e3fb1267e3c3 259 ++uip_acc32[0];
cassyarduino 0:e3fb1267e3c3 260 }
cassyarduino 0:e3fb1267e3c3 261 }
cassyarduino 0:e3fb1267e3c3 262
cassyarduino 0:e3fb1267e3c3 263
cassyarduino 0:e3fb1267e3c3 264 if(uip_acc32[3] < (op16 & 0xff)) {
cassyarduino 0:e3fb1267e3c3 265 ++uip_acc32[2];
cassyarduino 0:e3fb1267e3c3 266 if(uip_acc32[2] == 0) {
cassyarduino 0:e3fb1267e3c3 267 ++uip_acc32[1];
cassyarduino 0:e3fb1267e3c3 268 if(uip_acc32[1] == 0) {
cassyarduino 0:e3fb1267e3c3 269 ++uip_acc32[0];
cassyarduino 0:e3fb1267e3c3 270 }
cassyarduino 0:e3fb1267e3c3 271 }
cassyarduino 0:e3fb1267e3c3 272 }
cassyarduino 0:e3fb1267e3c3 273 }
cassyarduino 0:e3fb1267e3c3 274
cassyarduino 0:e3fb1267e3c3 275 #endif /* UIP_ARCH_ADD32 */
cassyarduino 0:e3fb1267e3c3 276
cassyarduino 0:e3fb1267e3c3 277 #if ! UIP_ARCH_CHKSUM
cassyarduino 0:e3fb1267e3c3 278 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 279 static u16_t
cassyarduino 0:e3fb1267e3c3 280 chksum(u16_t sum, const u8_t *data, u16_t len)
cassyarduino 0:e3fb1267e3c3 281 {
cassyarduino 0:e3fb1267e3c3 282 u16_t t;
cassyarduino 0:e3fb1267e3c3 283 const u8_t *dataptr;
cassyarduino 0:e3fb1267e3c3 284 const u8_t *last_byte;
cassyarduino 0:e3fb1267e3c3 285
cassyarduino 0:e3fb1267e3c3 286 dataptr = data;
cassyarduino 0:e3fb1267e3c3 287 last_byte = data + len - 1;
cassyarduino 0:e3fb1267e3c3 288
cassyarduino 0:e3fb1267e3c3 289 while(dataptr < last_byte) { /* At least two more bytes */
cassyarduino 0:e3fb1267e3c3 290 t = (dataptr[0] << 8) + dataptr[1];
cassyarduino 0:e3fb1267e3c3 291 sum += t;
cassyarduino 0:e3fb1267e3c3 292 if(sum < t) {
cassyarduino 0:e3fb1267e3c3 293 sum++; /* carry */
cassyarduino 0:e3fb1267e3c3 294 }
cassyarduino 0:e3fb1267e3c3 295 dataptr += 2;
cassyarduino 0:e3fb1267e3c3 296 }
cassyarduino 0:e3fb1267e3c3 297
cassyarduino 0:e3fb1267e3c3 298 if(dataptr == last_byte) {
cassyarduino 0:e3fb1267e3c3 299 t = (dataptr[0] << 8) + 0;
cassyarduino 0:e3fb1267e3c3 300 sum += t;
cassyarduino 0:e3fb1267e3c3 301 if(sum < t) {
cassyarduino 0:e3fb1267e3c3 302 sum++; /* carry */
cassyarduino 0:e3fb1267e3c3 303 }
cassyarduino 0:e3fb1267e3c3 304 }
cassyarduino 0:e3fb1267e3c3 305
cassyarduino 0:e3fb1267e3c3 306 /* Return sum in host byte order. */
cassyarduino 0:e3fb1267e3c3 307 return sum;
cassyarduino 0:e3fb1267e3c3 308 }
cassyarduino 0:e3fb1267e3c3 309 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 310 u16_t
cassyarduino 0:e3fb1267e3c3 311 uip_chksum(u16_t *data, u16_t len)
cassyarduino 0:e3fb1267e3c3 312 {
cassyarduino 0:e3fb1267e3c3 313 return htons(chksum(0, (u8_t *)data, len));
cassyarduino 0:e3fb1267e3c3 314 }
cassyarduino 0:e3fb1267e3c3 315 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 316 #ifndef UIP_ARCH_IPCHKSUM
cassyarduino 0:e3fb1267e3c3 317 u16_t
cassyarduino 0:e3fb1267e3c3 318 uip_ipchksum(void)
cassyarduino 0:e3fb1267e3c3 319 {
cassyarduino 0:e3fb1267e3c3 320 u16_t sum;
cassyarduino 0:e3fb1267e3c3 321
cassyarduino 0:e3fb1267e3c3 322 sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
cassyarduino 0:e3fb1267e3c3 323 DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
cassyarduino 0:e3fb1267e3c3 324 return (sum == 0) ? 0xffff : htons(sum);
cassyarduino 0:e3fb1267e3c3 325 }
cassyarduino 0:e3fb1267e3c3 326 #endif
cassyarduino 0:e3fb1267e3c3 327 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 328 static u16_t
cassyarduino 0:e3fb1267e3c3 329 upper_layer_chksum(u8_t proto)
cassyarduino 0:e3fb1267e3c3 330 {
cassyarduino 0:e3fb1267e3c3 331 u16_t upper_layer_len;
cassyarduino 0:e3fb1267e3c3 332 u16_t sum;
cassyarduino 0:e3fb1267e3c3 333
cassyarduino 0:e3fb1267e3c3 334 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 335 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
cassyarduino 0:e3fb1267e3c3 336 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 337 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
cassyarduino 0:e3fb1267e3c3 338 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 339
cassyarduino 0:e3fb1267e3c3 340 /* First sum pseudoheader. */
cassyarduino 0:e3fb1267e3c3 341
cassyarduino 0:e3fb1267e3c3 342 /* IP protocol and length fields. This addition cannot carry. */
cassyarduino 0:e3fb1267e3c3 343 sum = upper_layer_len + proto;
cassyarduino 0:e3fb1267e3c3 344 /* Sum IP source and destination addresses. */
cassyarduino 0:e3fb1267e3c3 345 sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
cassyarduino 0:e3fb1267e3c3 346
cassyarduino 0:e3fb1267e3c3 347 /* Sum TCP header and data. */
cassyarduino 0:e3fb1267e3c3 348 sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
cassyarduino 0:e3fb1267e3c3 349 upper_layer_len);
cassyarduino 0:e3fb1267e3c3 350
cassyarduino 0:e3fb1267e3c3 351 return (sum == 0) ? 0xffff : htons(sum);
cassyarduino 0:e3fb1267e3c3 352 }
cassyarduino 0:e3fb1267e3c3 353 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 354 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 355 u16_t
cassyarduino 0:e3fb1267e3c3 356 uip_icmp6chksum(void)
cassyarduino 0:e3fb1267e3c3 357 {
cassyarduino 0:e3fb1267e3c3 358 return upper_layer_chksum(UIP_PROTO_ICMP6);
cassyarduino 0:e3fb1267e3c3 359
cassyarduino 0:e3fb1267e3c3 360 }
cassyarduino 0:e3fb1267e3c3 361 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 362 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 363 u16_t
cassyarduino 0:e3fb1267e3c3 364 uip_tcpchksum(void)
cassyarduino 0:e3fb1267e3c3 365 {
cassyarduino 0:e3fb1267e3c3 366 return upper_layer_chksum(UIP_PROTO_TCP);
cassyarduino 0:e3fb1267e3c3 367 }
cassyarduino 0:e3fb1267e3c3 368 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 369 #if UIP_UDP_CHECKSUMS
cassyarduino 0:e3fb1267e3c3 370 u16_t
cassyarduino 0:e3fb1267e3c3 371 uip_udpchksum(void)
cassyarduino 0:e3fb1267e3c3 372 {
cassyarduino 0:e3fb1267e3c3 373 return upper_layer_chksum(UIP_PROTO_UDP);
cassyarduino 0:e3fb1267e3c3 374 }
cassyarduino 0:e3fb1267e3c3 375 #endif /* UIP_UDP_CHECKSUMS */
cassyarduino 0:e3fb1267e3c3 376 #endif /* UIP_ARCH_CHKSUM */
cassyarduino 0:e3fb1267e3c3 377 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 378 //"struct uip_conn {" in uip.h
cassyarduino 0:e3fb1267e3c3 379 void
cassyarduino 0:e3fb1267e3c3 380 uip_init(void)
cassyarduino 0:e3fb1267e3c3 381 {
cassyarduino 0:e3fb1267e3c3 382 for(c = 0; c < UIP_LISTENPORTS; ++c) {
cassyarduino 0:e3fb1267e3c3 383 uip_listenports[c] = 0;
cassyarduino 0:e3fb1267e3c3 384 }
cassyarduino 0:e3fb1267e3c3 385 for(c = 0; c < UIP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 386 uip_conns[c].tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 387 }
cassyarduino 0:e3fb1267e3c3 388 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 389 lastport = 1024;
cassyarduino 0:e3fb1267e3c3 390 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 391
cassyarduino 0:e3fb1267e3c3 392 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 393 for(c = 0; c < UIP_UDP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 394 uip_udp_conns[c].lport = 0;
cassyarduino 0:e3fb1267e3c3 395 }
cassyarduino 0:e3fb1267e3c3 396 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 397
cassyarduino 0:e3fb1267e3c3 398
cassyarduino 0:e3fb1267e3c3 399 /* IPv4 initialization. */
cassyarduino 0:e3fb1267e3c3 400 #if UIP_FIXEDADDR == 0
cassyarduino 0:e3fb1267e3c3 401 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
cassyarduino 0:e3fb1267e3c3 402 #endif /* UIP_FIXEDADDR */
cassyarduino 0:e3fb1267e3c3 403
cassyarduino 0:e3fb1267e3c3 404 }
cassyarduino 0:e3fb1267e3c3 405 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 406 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 407 struct uip_conn *
cassyarduino 0:e3fb1267e3c3 408 uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
cassyarduino 0:e3fb1267e3c3 409 {
cassyarduino 0:e3fb1267e3c3 410 register struct uip_conn *conn, *cconn;
cassyarduino 0:e3fb1267e3c3 411
cassyarduino 0:e3fb1267e3c3 412 /* Find an unused local port. */
cassyarduino 0:e3fb1267e3c3 413 again:
cassyarduino 0:e3fb1267e3c3 414 ++lastport;
cassyarduino 0:e3fb1267e3c3 415
cassyarduino 0:e3fb1267e3c3 416 if(lastport >= 32000) {
cassyarduino 0:e3fb1267e3c3 417 lastport = 4096;
cassyarduino 0:e3fb1267e3c3 418 }
cassyarduino 0:e3fb1267e3c3 419
cassyarduino 0:e3fb1267e3c3 420 /* Check if this port is already in use, and if so try to find
cassyarduino 0:e3fb1267e3c3 421 another one. */
cassyarduino 0:e3fb1267e3c3 422 for(c = 0; c < UIP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 423 conn = &uip_conns[c];
cassyarduino 0:e3fb1267e3c3 424 if(conn->tcpstateflags != UIP_CLOSED &&
cassyarduino 0:e3fb1267e3c3 425 conn->lport == htons(lastport)) {
cassyarduino 0:e3fb1267e3c3 426 goto again;
cassyarduino 0:e3fb1267e3c3 427 }
cassyarduino 0:e3fb1267e3c3 428 }
cassyarduino 0:e3fb1267e3c3 429
cassyarduino 0:e3fb1267e3c3 430 conn = 0;
cassyarduino 0:e3fb1267e3c3 431 for(c = 0; c < UIP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 432 cconn = &uip_conns[c];
cassyarduino 0:e3fb1267e3c3 433 if(cconn->tcpstateflags == UIP_CLOSED) {
cassyarduino 0:e3fb1267e3c3 434 conn = cconn;
cassyarduino 0:e3fb1267e3c3 435 break;
cassyarduino 0:e3fb1267e3c3 436 }
cassyarduino 0:e3fb1267e3c3 437 if(cconn->tcpstateflags == UIP_TIME_WAIT) {
cassyarduino 0:e3fb1267e3c3 438 if(conn == 0 ||
cassyarduino 0:e3fb1267e3c3 439 cconn->timer > conn->timer) {
cassyarduino 0:e3fb1267e3c3 440 conn = cconn;
cassyarduino 0:e3fb1267e3c3 441 }
cassyarduino 0:e3fb1267e3c3 442 }
cassyarduino 0:e3fb1267e3c3 443 }
cassyarduino 0:e3fb1267e3c3 444
cassyarduino 0:e3fb1267e3c3 445 if(conn == 0) {
cassyarduino 0:e3fb1267e3c3 446 return 0;
cassyarduino 0:e3fb1267e3c3 447 }
cassyarduino 0:e3fb1267e3c3 448
cassyarduino 0:e3fb1267e3c3 449 conn->tcpstateflags = UIP_SYN_SENT;
cassyarduino 0:e3fb1267e3c3 450
cassyarduino 0:e3fb1267e3c3 451 conn->snd_nxt[0] = iss[0];
cassyarduino 0:e3fb1267e3c3 452 conn->snd_nxt[1] = iss[1];
cassyarduino 0:e3fb1267e3c3 453 conn->snd_nxt[2] = iss[2];
cassyarduino 0:e3fb1267e3c3 454 conn->snd_nxt[3] = iss[3];
cassyarduino 0:e3fb1267e3c3 455
cassyarduino 0:e3fb1267e3c3 456 conn->initialmss = conn->mss = UIP_TCP_MSS;
cassyarduino 0:e3fb1267e3c3 457
cassyarduino 0:e3fb1267e3c3 458 conn->len = 1; /* TCP length of the SYN is one. */
cassyarduino 0:e3fb1267e3c3 459 conn->nrtx = 0;
cassyarduino 0:e3fb1267e3c3 460 conn->timer = 1; /* Send the SYN next time around. */
cassyarduino 0:e3fb1267e3c3 461 conn->rto = UIP_RTO;
cassyarduino 0:e3fb1267e3c3 462 conn->sa = 0;
cassyarduino 0:e3fb1267e3c3 463 conn->sv = 16; /* Initial value of the RTT variance. */
cassyarduino 0:e3fb1267e3c3 464 conn->lport = htons(lastport);
cassyarduino 0:e3fb1267e3c3 465 conn->rport = rport;
cassyarduino 0:e3fb1267e3c3 466 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
cassyarduino 0:e3fb1267e3c3 467
cassyarduino 0:e3fb1267e3c3 468 return conn;
cassyarduino 0:e3fb1267e3c3 469 }
cassyarduino 0:e3fb1267e3c3 470 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 471 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 472 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 473 struct uip_udp_conn *
cassyarduino 0:e3fb1267e3c3 474 uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
cassyarduino 0:e3fb1267e3c3 475 {
cassyarduino 0:e3fb1267e3c3 476 register struct uip_udp_conn *conn;
cassyarduino 0:e3fb1267e3c3 477
cassyarduino 0:e3fb1267e3c3 478 /* Find an unused local port. */
cassyarduino 0:e3fb1267e3c3 479 again:
cassyarduino 0:e3fb1267e3c3 480 ++lastport;
cassyarduino 0:e3fb1267e3c3 481
cassyarduino 0:e3fb1267e3c3 482 if(lastport >= 32000) {
cassyarduino 0:e3fb1267e3c3 483 lastport = 4096;
cassyarduino 0:e3fb1267e3c3 484 }
cassyarduino 0:e3fb1267e3c3 485
cassyarduino 0:e3fb1267e3c3 486 for(c = 0; c < UIP_UDP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 487 if(uip_udp_conns[c].lport == htons(lastport)) {
cassyarduino 0:e3fb1267e3c3 488 goto again;
cassyarduino 0:e3fb1267e3c3 489 }
cassyarduino 0:e3fb1267e3c3 490 }
cassyarduino 0:e3fb1267e3c3 491
cassyarduino 0:e3fb1267e3c3 492
cassyarduino 0:e3fb1267e3c3 493 conn = 0;
cassyarduino 0:e3fb1267e3c3 494 for(c = 0; c < UIP_UDP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 495 if(uip_udp_conns[c].lport == 0) {
cassyarduino 0:e3fb1267e3c3 496 conn = &uip_udp_conns[c];
cassyarduino 0:e3fb1267e3c3 497 break;
cassyarduino 0:e3fb1267e3c3 498 }
cassyarduino 0:e3fb1267e3c3 499 }
cassyarduino 0:e3fb1267e3c3 500
cassyarduino 0:e3fb1267e3c3 501 if(conn == 0) {
cassyarduino 0:e3fb1267e3c3 502 return 0;
cassyarduino 0:e3fb1267e3c3 503 }
cassyarduino 0:e3fb1267e3c3 504
cassyarduino 0:e3fb1267e3c3 505 conn->lport = HTONS(lastport);
cassyarduino 0:e3fb1267e3c3 506 conn->rport = rport;
cassyarduino 0:e3fb1267e3c3 507 if(ripaddr == NULL) {
cassyarduino 0:e3fb1267e3c3 508 memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
cassyarduino 0:e3fb1267e3c3 509 } else {
cassyarduino 0:e3fb1267e3c3 510 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
cassyarduino 0:e3fb1267e3c3 511 }
cassyarduino 0:e3fb1267e3c3 512 conn->ttl = UIP_TTL;
cassyarduino 0:e3fb1267e3c3 513
cassyarduino 0:e3fb1267e3c3 514 return conn;
cassyarduino 0:e3fb1267e3c3 515 }
cassyarduino 0:e3fb1267e3c3 516 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 517 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 518 void
cassyarduino 0:e3fb1267e3c3 519 uip_unlisten(u16_t port)
cassyarduino 0:e3fb1267e3c3 520 {
cassyarduino 0:e3fb1267e3c3 521 for(c = 0; c < UIP_LISTENPORTS; ++c) {
cassyarduino 0:e3fb1267e3c3 522 if(uip_listenports[c] == port) {
cassyarduino 0:e3fb1267e3c3 523 uip_listenports[c] = 0;
cassyarduino 0:e3fb1267e3c3 524 return;
cassyarduino 0:e3fb1267e3c3 525 }
cassyarduino 0:e3fb1267e3c3 526 }
cassyarduino 0:e3fb1267e3c3 527 }
cassyarduino 0:e3fb1267e3c3 528 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 529 void
cassyarduino 0:e3fb1267e3c3 530 uip_listen(u16_t port)
cassyarduino 0:e3fb1267e3c3 531 {
cassyarduino 0:e3fb1267e3c3 532 for(c = 0; c < UIP_LISTENPORTS; ++c) {
cassyarduino 0:e3fb1267e3c3 533 if(uip_listenports[c] == 0) {
cassyarduino 0:e3fb1267e3c3 534 uip_listenports[c] = port;
cassyarduino 0:e3fb1267e3c3 535 return;
cassyarduino 0:e3fb1267e3c3 536 }
cassyarduino 0:e3fb1267e3c3 537 }
cassyarduino 0:e3fb1267e3c3 538 }
cassyarduino 0:e3fb1267e3c3 539 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 540 /* XXX: IP fragment reassembly: not well-tested. */
cassyarduino 0:e3fb1267e3c3 541
cassyarduino 0:e3fb1267e3c3 542 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 543 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
cassyarduino 0:e3fb1267e3c3 544 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
cassyarduino 0:e3fb1267e3c3 545 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
cassyarduino 0:e3fb1267e3c3 546 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
cassyarduino 0:e3fb1267e3c3 547 0x0f, 0x07, 0x03, 0x01};
cassyarduino 0:e3fb1267e3c3 548 static u16_t uip_reasslen;
cassyarduino 0:e3fb1267e3c3 549 static u8_t uip_reassflags;
cassyarduino 0:e3fb1267e3c3 550 #define UIP_REASS_FLAG_LASTFRAG 0x01
cassyarduino 0:e3fb1267e3c3 551 static u8_t uip_reasstmr;
cassyarduino 0:e3fb1267e3c3 552
cassyarduino 0:e3fb1267e3c3 553 #define IP_MF 0x20
cassyarduino 0:e3fb1267e3c3 554
cassyarduino 0:e3fb1267e3c3 555 static u8_t
cassyarduino 0:e3fb1267e3c3 556 uip_reass(void)
cassyarduino 0:e3fb1267e3c3 557 {
cassyarduino 0:e3fb1267e3c3 558 u16_t offset, len;
cassyarduino 0:e3fb1267e3c3 559 u16_t i;
cassyarduino 0:e3fb1267e3c3 560
cassyarduino 0:e3fb1267e3c3 561 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
cassyarduino 0:e3fb1267e3c3 562 write the IP header of the fragment into the reassembly
cassyarduino 0:e3fb1267e3c3 563 buffer. The timer is updated with the maximum age. */
cassyarduino 0:e3fb1267e3c3 564 if(uip_reasstmr == 0) {
cassyarduino 0:e3fb1267e3c3 565 memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
cassyarduino 0:e3fb1267e3c3 566 uip_reasstmr = UIP_REASS_MAXAGE;
cassyarduino 0:e3fb1267e3c3 567 uip_reassflags = 0;
cassyarduino 0:e3fb1267e3c3 568 /* Clear the bitmap. */
cassyarduino 0:e3fb1267e3c3 569 memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
cassyarduino 0:e3fb1267e3c3 570 }
cassyarduino 0:e3fb1267e3c3 571
cassyarduino 0:e3fb1267e3c3 572 /* Check if the incoming fragment matches the one currently present
cassyarduino 0:e3fb1267e3c3 573 in the reasembly buffer. If so, we proceed with copying the
cassyarduino 0:e3fb1267e3c3 574 fragment into the buffer. */
cassyarduino 0:e3fb1267e3c3 575 if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
cassyarduino 0:e3fb1267e3c3 576 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
cassyarduino 0:e3fb1267e3c3 577 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
cassyarduino 0:e3fb1267e3c3 578 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
cassyarduino 0:e3fb1267e3c3 579 BUF->ipid[0] == FBUF->ipid[0] &&
cassyarduino 0:e3fb1267e3c3 580 BUF->ipid[1] == FBUF->ipid[1]) {
cassyarduino 0:e3fb1267e3c3 581
cassyarduino 0:e3fb1267e3c3 582 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
cassyarduino 0:e3fb1267e3c3 583 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
cassyarduino 0:e3fb1267e3c3 584
cassyarduino 0:e3fb1267e3c3 585 /* If the offset or the offset + fragment length overflows the
cassyarduino 0:e3fb1267e3c3 586 reassembly buffer, we discard the entire packet. */
cassyarduino 0:e3fb1267e3c3 587 if(offset > UIP_REASS_BUFSIZE ||
cassyarduino 0:e3fb1267e3c3 588 offset + len > UIP_REASS_BUFSIZE) {
cassyarduino 0:e3fb1267e3c3 589 uip_reasstmr = 0;
cassyarduino 0:e3fb1267e3c3 590 goto nullreturn;
cassyarduino 0:e3fb1267e3c3 591 }
cassyarduino 0:e3fb1267e3c3 592
cassyarduino 0:e3fb1267e3c3 593 /* Copy the fragment into the reassembly buffer, at the right
cassyarduino 0:e3fb1267e3c3 594 offset. */
cassyarduino 0:e3fb1267e3c3 595 memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
cassyarduino 0:e3fb1267e3c3 596 (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
cassyarduino 0:e3fb1267e3c3 597 len);
cassyarduino 0:e3fb1267e3c3 598
cassyarduino 0:e3fb1267e3c3 599 /* Update the bitmap. */
cassyarduino 0:e3fb1267e3c3 600 if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
cassyarduino 0:e3fb1267e3c3 601 /* If the two endpoints are in the same byte, we only update
cassyarduino 0:e3fb1267e3c3 602 that byte. */
cassyarduino 0:e3fb1267e3c3 603
cassyarduino 0:e3fb1267e3c3 604 uip_reassbitmap[offset / (8 * 8)] |=
cassyarduino 0:e3fb1267e3c3 605 bitmap_bits[(offset / 8 ) & 7] &
cassyarduino 0:e3fb1267e3c3 606 ~bitmap_bits[((offset + len) / 8 ) & 7];
cassyarduino 0:e3fb1267e3c3 607 } else {
cassyarduino 0:e3fb1267e3c3 608 /* If the two endpoints are in different bytes, we update the
cassyarduino 0:e3fb1267e3c3 609 bytes in the endpoints and fill the stuff inbetween with
cassyarduino 0:e3fb1267e3c3 610 0xff. */
cassyarduino 0:e3fb1267e3c3 611 uip_reassbitmap[offset / (8 * 8)] |=
cassyarduino 0:e3fb1267e3c3 612 bitmap_bits[(offset / 8 ) & 7];
cassyarduino 0:e3fb1267e3c3 613 for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
cassyarduino 0:e3fb1267e3c3 614 uip_reassbitmap[i] = 0xff;
cassyarduino 0:e3fb1267e3c3 615 }
cassyarduino 0:e3fb1267e3c3 616 uip_reassbitmap[(offset + len) / (8 * 8)] |=
cassyarduino 0:e3fb1267e3c3 617 ~bitmap_bits[((offset + len) / 8 ) & 7];
cassyarduino 0:e3fb1267e3c3 618 }
cassyarduino 0:e3fb1267e3c3 619
cassyarduino 0:e3fb1267e3c3 620 /* If this fragment has the More Fragments flag set to zero, we
cassyarduino 0:e3fb1267e3c3 621 know that this is the last fragment, so we can calculate the
cassyarduino 0:e3fb1267e3c3 622 size of the entire packet. We also set the
cassyarduino 0:e3fb1267e3c3 623 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
cassyarduino 0:e3fb1267e3c3 624 the final fragment. */
cassyarduino 0:e3fb1267e3c3 625
cassyarduino 0:e3fb1267e3c3 626 if((BUF->ipoffset[0] & IP_MF) == 0) {
cassyarduino 0:e3fb1267e3c3 627 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
cassyarduino 0:e3fb1267e3c3 628 uip_reasslen = offset + len;
cassyarduino 0:e3fb1267e3c3 629 }
cassyarduino 0:e3fb1267e3c3 630
cassyarduino 0:e3fb1267e3c3 631 /* Finally, we check if we have a full packet in the buffer. We do
cassyarduino 0:e3fb1267e3c3 632 this by checking if we have the last fragment and if all bits
cassyarduino 0:e3fb1267e3c3 633 in the bitmap are set. */
cassyarduino 0:e3fb1267e3c3 634 if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
cassyarduino 0:e3fb1267e3c3 635 /* Check all bytes up to and including all but the last byte in
cassyarduino 0:e3fb1267e3c3 636 the bitmap. */
cassyarduino 0:e3fb1267e3c3 637 for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
cassyarduino 0:e3fb1267e3c3 638 if(uip_reassbitmap[i] != 0xff) {
cassyarduino 0:e3fb1267e3c3 639 goto nullreturn;
cassyarduino 0:e3fb1267e3c3 640 }
cassyarduino 0:e3fb1267e3c3 641 }
cassyarduino 0:e3fb1267e3c3 642 /* Check the last byte in the bitmap. It should contain just the
cassyarduino 0:e3fb1267e3c3 643 right amount of bits. */
cassyarduino 0:e3fb1267e3c3 644 if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
cassyarduino 0:e3fb1267e3c3 645 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
cassyarduino 0:e3fb1267e3c3 646 goto nullreturn;
cassyarduino 0:e3fb1267e3c3 647 }
cassyarduino 0:e3fb1267e3c3 648
cassyarduino 0:e3fb1267e3c3 649 /* If we have come this far, we have a full packet in the
cassyarduino 0:e3fb1267e3c3 650 buffer, so we allocate a pbuf and copy the packet into it. We
cassyarduino 0:e3fb1267e3c3 651 also reset the timer. */
cassyarduino 0:e3fb1267e3c3 652 uip_reasstmr = 0;
cassyarduino 0:e3fb1267e3c3 653 memcpy(BUF, FBUF, uip_reasslen);
cassyarduino 0:e3fb1267e3c3 654
cassyarduino 0:e3fb1267e3c3 655 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
cassyarduino 0:e3fb1267e3c3 656 from now on. */
cassyarduino 0:e3fb1267e3c3 657 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
cassyarduino 0:e3fb1267e3c3 658 BUF->len[0] = uip_reasslen >> 8;
cassyarduino 0:e3fb1267e3c3 659 BUF->len[1] = uip_reasslen & 0xff;
cassyarduino 0:e3fb1267e3c3 660 BUF->ipchksum = 0;
cassyarduino 0:e3fb1267e3c3 661 BUF->ipchksum = ~(uip_ipchksum());
cassyarduino 0:e3fb1267e3c3 662
cassyarduino 0:e3fb1267e3c3 663 return uip_reasslen;
cassyarduino 0:e3fb1267e3c3 664 }
cassyarduino 0:e3fb1267e3c3 665 }
cassyarduino 0:e3fb1267e3c3 666
cassyarduino 0:e3fb1267e3c3 667 nullreturn:
cassyarduino 0:e3fb1267e3c3 668 return 0;
cassyarduino 0:e3fb1267e3c3 669 }
cassyarduino 0:e3fb1267e3c3 670 #endif /* UIP_REASSEMBLY */
cassyarduino 0:e3fb1267e3c3 671 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 672 static void
cassyarduino 0:e3fb1267e3c3 673 uip_add_rcv_nxt(u16_t n)
cassyarduino 0:e3fb1267e3c3 674 {
cassyarduino 0:e3fb1267e3c3 675 uip_add32(uip_conn->rcv_nxt, n);
cassyarduino 0:e3fb1267e3c3 676 uip_conn->rcv_nxt[0] = uip_acc32[0];
cassyarduino 0:e3fb1267e3c3 677 uip_conn->rcv_nxt[1] = uip_acc32[1];
cassyarduino 0:e3fb1267e3c3 678 uip_conn->rcv_nxt[2] = uip_acc32[2];
cassyarduino 0:e3fb1267e3c3 679 uip_conn->rcv_nxt[3] = uip_acc32[3];
cassyarduino 0:e3fb1267e3c3 680 }
cassyarduino 0:e3fb1267e3c3 681 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 682 void
cassyarduino 0:e3fb1267e3c3 683 uip_process(u8_t flag)
cassyarduino 0:e3fb1267e3c3 684 {
cassyarduino 0:e3fb1267e3c3 685 register struct uip_conn *uip_connr = uip_conn;
cassyarduino 0:e3fb1267e3c3 686
cassyarduino 0:e3fb1267e3c3 687 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 688 if(flag == UIP_UDP_SEND_CONN) {
cassyarduino 0:e3fb1267e3c3 689 goto udp_send;
cassyarduino 0:e3fb1267e3c3 690 }
cassyarduino 0:e3fb1267e3c3 691 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 692
cassyarduino 0:e3fb1267e3c3 693 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
cassyarduino 0:e3fb1267e3c3 694
cassyarduino 0:e3fb1267e3c3 695 /* Check if we were invoked because of a poll request for a
cassyarduino 0:e3fb1267e3c3 696 particular connection. */
cassyarduino 0:e3fb1267e3c3 697 if(flag == UIP_POLL_REQUEST) {
cassyarduino 0:e3fb1267e3c3 698 if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
cassyarduino 0:e3fb1267e3c3 699 !uip_outstanding(uip_connr)) {
cassyarduino 0:e3fb1267e3c3 700 uip_flags = UIP_POLL;
cassyarduino 0:e3fb1267e3c3 701 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 702 goto appsend;
cassyarduino 0:e3fb1267e3c3 703 }
cassyarduino 0:e3fb1267e3c3 704 goto drop;
cassyarduino 0:e3fb1267e3c3 705
cassyarduino 0:e3fb1267e3c3 706 /* Check if we were invoked because of the perodic timer fireing. */
cassyarduino 0:e3fb1267e3c3 707 } else if(flag == UIP_TIMER) {
cassyarduino 0:e3fb1267e3c3 708 #if UIP_REASSEMBLY
cassyarduino 0:e3fb1267e3c3 709 if(uip_reasstmr != 0) {
cassyarduino 0:e3fb1267e3c3 710 --uip_reasstmr;
cassyarduino 0:e3fb1267e3c3 711 }
cassyarduino 0:e3fb1267e3c3 712 #endif /* UIP_REASSEMBLY */
cassyarduino 0:e3fb1267e3c3 713 /* Increase the initial sequence number. */
cassyarduino 0:e3fb1267e3c3 714 if(++iss[3] == 0) {
cassyarduino 0:e3fb1267e3c3 715 if(++iss[2] == 0) {
cassyarduino 0:e3fb1267e3c3 716 if(++iss[1] == 0) {
cassyarduino 0:e3fb1267e3c3 717 ++iss[0];
cassyarduino 0:e3fb1267e3c3 718 }
cassyarduino 0:e3fb1267e3c3 719 }
cassyarduino 0:e3fb1267e3c3 720 }
cassyarduino 0:e3fb1267e3c3 721
cassyarduino 0:e3fb1267e3c3 722 /* Reset the length variables. */
cassyarduino 0:e3fb1267e3c3 723 uip_len = 0;
cassyarduino 0:e3fb1267e3c3 724 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 725
cassyarduino 0:e3fb1267e3c3 726 /* Check if the connection is in a state in which we simply wait
cassyarduino 0:e3fb1267e3c3 727 for the connection to time out. If so, we increase the
cassyarduino 0:e3fb1267e3c3 728 connection's timer and remove the connection if it times
cassyarduino 0:e3fb1267e3c3 729 out. */
cassyarduino 0:e3fb1267e3c3 730 if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
cassyarduino 0:e3fb1267e3c3 731 uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
cassyarduino 0:e3fb1267e3c3 732 ++(uip_connr->timer);
cassyarduino 0:e3fb1267e3c3 733 if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
cassyarduino 0:e3fb1267e3c3 734 uip_connr->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 735 }
cassyarduino 0:e3fb1267e3c3 736 } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
cassyarduino 0:e3fb1267e3c3 737 /* If the connection has outstanding data, we increase the
cassyarduino 0:e3fb1267e3c3 738 connection's timer and see if it has reached the RTO value
cassyarduino 0:e3fb1267e3c3 739 in which case we retransmit. */
cassyarduino 0:e3fb1267e3c3 740 if(uip_outstanding(uip_connr)) {
cassyarduino 0:e3fb1267e3c3 741 if(uip_connr->timer-- == 0) {
cassyarduino 0:e3fb1267e3c3 742 if(uip_connr->nrtx == UIP_MAXRTX ||
cassyarduino 0:e3fb1267e3c3 743 ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
cassyarduino 0:e3fb1267e3c3 744 uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
cassyarduino 0:e3fb1267e3c3 745 uip_connr->nrtx == UIP_MAXSYNRTX)) {
cassyarduino 0:e3fb1267e3c3 746 uip_connr->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 747
cassyarduino 0:e3fb1267e3c3 748 /* We call UIP_APPCALL() with uip_flags set to
cassyarduino 0:e3fb1267e3c3 749 UIP_TIMEDOUT to inform the application that the
cassyarduino 0:e3fb1267e3c3 750 connection has timed out. */
cassyarduino 0:e3fb1267e3c3 751 uip_flags = UIP_TIMEDOUT;
cassyarduino 0:e3fb1267e3c3 752 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 753
cassyarduino 0:e3fb1267e3c3 754 /* We also send a reset packet to the remote host. */
cassyarduino 0:e3fb1267e3c3 755 BUF->flags = TCP_RST | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 756 goto tcp_send_nodata;
cassyarduino 0:e3fb1267e3c3 757 }
cassyarduino 0:e3fb1267e3c3 758
cassyarduino 0:e3fb1267e3c3 759 /* Exponential backoff. */
cassyarduino 0:e3fb1267e3c3 760 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
cassyarduino 0:e3fb1267e3c3 761 4:
cassyarduino 0:e3fb1267e3c3 762 uip_connr->nrtx);
cassyarduino 0:e3fb1267e3c3 763 ++(uip_connr->nrtx);
cassyarduino 0:e3fb1267e3c3 764
cassyarduino 0:e3fb1267e3c3 765 /* Ok, so we need to retransmit. We do this differently
cassyarduino 0:e3fb1267e3c3 766 depending on which state we are in. In ESTABLISHED, we
cassyarduino 0:e3fb1267e3c3 767 call upon the application so that it may prepare the
cassyarduino 0:e3fb1267e3c3 768 data for the retransmit. In SYN_RCVD, we resend the
cassyarduino 0:e3fb1267e3c3 769 SYNACK that we sent earlier and in LAST_ACK we have to
cassyarduino 0:e3fb1267e3c3 770 retransmit our FINACK. */
cassyarduino 0:e3fb1267e3c3 771 UIP_STAT(++uip_stat.tcp.rexmit);
cassyarduino 0:e3fb1267e3c3 772 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
cassyarduino 0:e3fb1267e3c3 773 case UIP_SYN_RCVD:
cassyarduino 0:e3fb1267e3c3 774 /* In the SYN_RCVD state, we should retransmit our
cassyarduino 0:e3fb1267e3c3 775 SYNACK. */
cassyarduino 0:e3fb1267e3c3 776 goto tcp_send_synack;
cassyarduino 0:e3fb1267e3c3 777
cassyarduino 0:e3fb1267e3c3 778 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 779 case UIP_SYN_SENT:
cassyarduino 0:e3fb1267e3c3 780 /* In the SYN_SENT state, we retransmit out SYN. */
cassyarduino 0:e3fb1267e3c3 781 BUF->flags = 0;
cassyarduino 0:e3fb1267e3c3 782 goto tcp_send_syn;
cassyarduino 0:e3fb1267e3c3 783 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 784
cassyarduino 0:e3fb1267e3c3 785 case UIP_ESTABLISHED:
cassyarduino 0:e3fb1267e3c3 786 /* In the ESTABLISHED state, we call upon the application
cassyarduino 0:e3fb1267e3c3 787 to do the actual retransmit after which we jump into
cassyarduino 0:e3fb1267e3c3 788 the code for sending out the packet (the apprexmit
cassyarduino 0:e3fb1267e3c3 789 label). */
cassyarduino 0:e3fb1267e3c3 790 uip_flags = UIP_REXMIT;
cassyarduino 0:e3fb1267e3c3 791 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 792 goto apprexmit;
cassyarduino 0:e3fb1267e3c3 793
cassyarduino 0:e3fb1267e3c3 794 case UIP_FIN_WAIT_1:
cassyarduino 0:e3fb1267e3c3 795 case UIP_CLOSING:
cassyarduino 0:e3fb1267e3c3 796 case UIP_LAST_ACK:
cassyarduino 0:e3fb1267e3c3 797 /* In all these states we should retransmit a FINACK. */
cassyarduino 0:e3fb1267e3c3 798 goto tcp_send_finack;
cassyarduino 0:e3fb1267e3c3 799
cassyarduino 0:e3fb1267e3c3 800 }
cassyarduino 0:e3fb1267e3c3 801 }
cassyarduino 0:e3fb1267e3c3 802 } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
cassyarduino 0:e3fb1267e3c3 803 /* If there was no need for a retransmission, we poll the
cassyarduino 0:e3fb1267e3c3 804 application for new data. */
cassyarduino 0:e3fb1267e3c3 805 uip_flags = UIP_POLL;
cassyarduino 0:e3fb1267e3c3 806 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 807 goto appsend;
cassyarduino 0:e3fb1267e3c3 808 }
cassyarduino 0:e3fb1267e3c3 809 }
cassyarduino 0:e3fb1267e3c3 810 goto drop;
cassyarduino 0:e3fb1267e3c3 811 }
cassyarduino 0:e3fb1267e3c3 812 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 813 if(flag == UIP_UDP_TIMER) {
cassyarduino 0:e3fb1267e3c3 814 if(uip_udp_conn->lport != 0) {
cassyarduino 0:e3fb1267e3c3 815 uip_conn = NULL;
cassyarduino 0:e3fb1267e3c3 816 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
cassyarduino 0:e3fb1267e3c3 817 uip_len = uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 818 uip_flags = UIP_POLL;
cassyarduino 0:e3fb1267e3c3 819 UIP_UDP_APPCALL();
cassyarduino 0:e3fb1267e3c3 820 goto udp_send;
cassyarduino 0:e3fb1267e3c3 821 } else {
cassyarduino 0:e3fb1267e3c3 822 goto drop;
cassyarduino 0:e3fb1267e3c3 823 }
cassyarduino 0:e3fb1267e3c3 824 }
cassyarduino 0:e3fb1267e3c3 825 #endif
cassyarduino 0:e3fb1267e3c3 826
cassyarduino 0:e3fb1267e3c3 827 /* This is where the input processing starts. */
cassyarduino 0:e3fb1267e3c3 828 UIP_STAT(++uip_stat.ip.recv);
cassyarduino 0:e3fb1267e3c3 829
cassyarduino 0:e3fb1267e3c3 830 /* Start of IP input header processing code. */
cassyarduino 0:e3fb1267e3c3 831
cassyarduino 0:e3fb1267e3c3 832 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 833 /* Check validity of the IP header. */
cassyarduino 0:e3fb1267e3c3 834 if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
cassyarduino 0:e3fb1267e3c3 835 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 836 UIP_STAT(++uip_stat.ip.vhlerr);
cassyarduino 0:e3fb1267e3c3 837 UIP_LOG("ipv6: invalid version.");
cassyarduino 0:e3fb1267e3c3 838 goto drop;
cassyarduino 0:e3fb1267e3c3 839 }
cassyarduino 0:e3fb1267e3c3 840 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 841 /* Check validity of the IP header. */
cassyarduino 0:e3fb1267e3c3 842 if(BUF->vhl != 0x45) { /* IP version and header length. */
cassyarduino 0:e3fb1267e3c3 843 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 844 UIP_STAT(++uip_stat.ip.vhlerr);
cassyarduino 0:e3fb1267e3c3 845 UIP_LOG("ip: invalid version or header length.");
cassyarduino 0:e3fb1267e3c3 846 goto drop;
cassyarduino 0:e3fb1267e3c3 847 }
cassyarduino 0:e3fb1267e3c3 848 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 849
cassyarduino 0:e3fb1267e3c3 850 /* Check the size of the packet. If the size reported to us in
cassyarduino 0:e3fb1267e3c3 851 uip_len is smaller the size reported in the IP header, we assume
cassyarduino 0:e3fb1267e3c3 852 that the packet has been corrupted in transit. If the size of
cassyarduino 0:e3fb1267e3c3 853 uip_len is larger than the size reported in the IP packet header,
cassyarduino 0:e3fb1267e3c3 854 the packet has been padded and we set uip_len to the correct
cassyarduino 0:e3fb1267e3c3 855 value.. */
cassyarduino 0:e3fb1267e3c3 856
cassyarduino 0:e3fb1267e3c3 857 if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
cassyarduino 0:e3fb1267e3c3 858 uip_len = (BUF->len[0] << 8) + BUF->len[1];
cassyarduino 0:e3fb1267e3c3 859 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 860 uip_len += 40; /* The length reported in the IPv6 header is the
cassyarduino 0:e3fb1267e3c3 861 length of the payload that follows the
cassyarduino 0:e3fb1267e3c3 862 header. However, uIP uses the uip_len variable
cassyarduino 0:e3fb1267e3c3 863 for holding the size of the entire packet,
cassyarduino 0:e3fb1267e3c3 864 including the IP header. For IPv4 this is not a
cassyarduino 0:e3fb1267e3c3 865 problem as the length field in the IPv4 header
cassyarduino 0:e3fb1267e3c3 866 contains the length of the entire packet. But
cassyarduino 0:e3fb1267e3c3 867 for IPv6 we need to add the size of the IPv6
cassyarduino 0:e3fb1267e3c3 868 header (40 bytes). */
cassyarduino 0:e3fb1267e3c3 869 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 870 } else {
cassyarduino 0:e3fb1267e3c3 871 UIP_LOG("ip: packet shorter than reported in IP header.");
cassyarduino 0:e3fb1267e3c3 872 goto drop;
cassyarduino 0:e3fb1267e3c3 873 }
cassyarduino 0:e3fb1267e3c3 874
cassyarduino 0:e3fb1267e3c3 875 #if !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 876 /* Check the fragment flag. */
cassyarduino 0:e3fb1267e3c3 877 if((BUF->ipoffset[0] & 0x3f) != 0 ||
cassyarduino 0:e3fb1267e3c3 878 BUF->ipoffset[1] != 0) {
cassyarduino 0:e3fb1267e3c3 879 #if UIP_REASSEMBLY
cassyarduino 0:e3fb1267e3c3 880 uip_len = uip_reass();
cassyarduino 0:e3fb1267e3c3 881 if(uip_len == 0) {
cassyarduino 0:e3fb1267e3c3 882 goto drop;
cassyarduino 0:e3fb1267e3c3 883 }
cassyarduino 0:e3fb1267e3c3 884 #else /* UIP_REASSEMBLY */
cassyarduino 0:e3fb1267e3c3 885 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 886 UIP_STAT(++uip_stat.ip.fragerr);
cassyarduino 0:e3fb1267e3c3 887 UIP_LOG("ip: fragment dropped.");
cassyarduino 0:e3fb1267e3c3 888 goto drop;
cassyarduino 0:e3fb1267e3c3 889 #endif /* UIP_REASSEMBLY */
cassyarduino 0:e3fb1267e3c3 890 }
cassyarduino 0:e3fb1267e3c3 891 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 892
cassyarduino 0:e3fb1267e3c3 893 if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
cassyarduino 0:e3fb1267e3c3 894 /* If we are configured to use ping IP address configuration and
cassyarduino 0:e3fb1267e3c3 895 hasn't been assigned an IP address yet, we accept all ICMP
cassyarduino 0:e3fb1267e3c3 896 packets. */
cassyarduino 0:e3fb1267e3c3 897 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 898 if(BUF->proto == UIP_PROTO_ICMP) {
cassyarduino 0:e3fb1267e3c3 899 UIP_LOG("ip: possible ping config packet received.");
cassyarduino 0:e3fb1267e3c3 900 goto icmp_input;
cassyarduino 0:e3fb1267e3c3 901 } else {
cassyarduino 0:e3fb1267e3c3 902 UIP_LOG("ip: packet dropped since no address assigned.");
cassyarduino 0:e3fb1267e3c3 903 goto drop;
cassyarduino 0:e3fb1267e3c3 904 }
cassyarduino 0:e3fb1267e3c3 905 #endif /* UIP_PINGADDRCONF */
cassyarduino 0:e3fb1267e3c3 906
cassyarduino 0:e3fb1267e3c3 907 } else {
cassyarduino 0:e3fb1267e3c3 908 /* If IP broadcast support is configured, we check for a broadcast
cassyarduino 0:e3fb1267e3c3 909 UDP packet, which may be destined to us. */
cassyarduino 0:e3fb1267e3c3 910 #if UIP_BROADCAST
cassyarduino 0:e3fb1267e3c3 911 DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
cassyarduino 36:689bcc358067 912 if(BUF->proto == UIP_PROTO_UDP && (
cassyarduino 36:689bcc358067 913 uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) // Limited broadcast
cassyarduino 36:689bcc358067 914 || ((BUF->destipaddr[0]==(uip_hostaddr[0] | (~uip_netmask[0]))) && (BUF->destipaddr[1]==(uip_hostaddr[1] | (~uip_netmask[1])))) // Direct broadcast
cassyarduino 36:689bcc358067 915 )
cassyarduino 0:e3fb1267e3c3 916 /*&&
cassyarduino 0:e3fb1267e3c3 917 uip_ipchksum() == 0xffff*/) {
cassyarduino 0:e3fb1267e3c3 918 goto udp_input;
cassyarduino 0:e3fb1267e3c3 919 }
cassyarduino 0:e3fb1267e3c3 920 #endif /* UIP_BROADCAST */
cassyarduino 0:e3fb1267e3c3 921
cassyarduino 0:e3fb1267e3c3 922 /* Check if the packet is destined for our IP address. */
cassyarduino 0:e3fb1267e3c3 923 #if !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 924 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
cassyarduino 0:e3fb1267e3c3 925 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 926 goto drop;
cassyarduino 0:e3fb1267e3c3 927 }
cassyarduino 0:e3fb1267e3c3 928 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 929 /* For IPv6, packet reception is a little trickier as we need to
cassyarduino 0:e3fb1267e3c3 930 make sure that we listen to certain multicast addresses (all
cassyarduino 0:e3fb1267e3c3 931 hosts multicast address, and the solicited-node multicast
cassyarduino 0:e3fb1267e3c3 932 address) as well. However, we will cheat here and accept all
cassyarduino 0:e3fb1267e3c3 933 multicast packets that are sent to the ff02::/16 addresses. */
cassyarduino 0:e3fb1267e3c3 934 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
cassyarduino 0:e3fb1267e3c3 935 BUF->destipaddr[0] != HTONS(0xff02)) {
cassyarduino 0:e3fb1267e3c3 936 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 937 goto drop;
cassyarduino 0:e3fb1267e3c3 938 }
cassyarduino 0:e3fb1267e3c3 939 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 940 }
cassyarduino 0:e3fb1267e3c3 941
cassyarduino 0:e3fb1267e3c3 942 #if !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 943 if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
cassyarduino 0:e3fb1267e3c3 944 checksum. */
cassyarduino 0:e3fb1267e3c3 945 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 946 UIP_STAT(++uip_stat.ip.chkerr);
cassyarduino 0:e3fb1267e3c3 947 UIP_LOG("ip: bad checksum.");
cassyarduino 0:e3fb1267e3c3 948 goto drop;
cassyarduino 0:e3fb1267e3c3 949 }
cassyarduino 0:e3fb1267e3c3 950 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 951
cassyarduino 0:e3fb1267e3c3 952 if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
cassyarduino 0:e3fb1267e3c3 953 proceed with TCP input
cassyarduino 0:e3fb1267e3c3 954 processing. */
cassyarduino 0:e3fb1267e3c3 955 goto tcp_input;
cassyarduino 0:e3fb1267e3c3 956 }
cassyarduino 0:e3fb1267e3c3 957
cassyarduino 0:e3fb1267e3c3 958 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 959 if(BUF->proto == UIP_PROTO_UDP) {
cassyarduino 0:e3fb1267e3c3 960 goto udp_input;
cassyarduino 0:e3fb1267e3c3 961 }
cassyarduino 0:e3fb1267e3c3 962 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 963
cassyarduino 0:e3fb1267e3c3 964 #if !UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 965 /* ICMPv4 processing code follows. */
cassyarduino 0:e3fb1267e3c3 966 if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
cassyarduino 0:e3fb1267e3c3 967 here. */
cassyarduino 0:e3fb1267e3c3 968 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 969 UIP_STAT(++uip_stat.ip.protoerr);
cassyarduino 0:e3fb1267e3c3 970 UIP_LOG("ip: neither tcp nor icmp.");
cassyarduino 0:e3fb1267e3c3 971 goto drop;
cassyarduino 0:e3fb1267e3c3 972 }
cassyarduino 0:e3fb1267e3c3 973
cassyarduino 0:e3fb1267e3c3 974 #if UIP_PINGADDRCONF
cassyarduino 0:e3fb1267e3c3 975 icmp_input:
cassyarduino 0:e3fb1267e3c3 976 #endif /* UIP_PINGADDRCONF */
cassyarduino 0:e3fb1267e3c3 977 UIP_STAT(++uip_stat.icmp.recv);
cassyarduino 0:e3fb1267e3c3 978
cassyarduino 0:e3fb1267e3c3 979 /* ICMP echo (i.e., ping) processing. This is simple, we only change
cassyarduino 0:e3fb1267e3c3 980 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
cassyarduino 0:e3fb1267e3c3 981 checksum before we return the packet. */
cassyarduino 0:e3fb1267e3c3 982 if(ICMPBUF->type != ICMP_ECHO) {
cassyarduino 0:e3fb1267e3c3 983 UIP_STAT(++uip_stat.icmp.drop);
cassyarduino 0:e3fb1267e3c3 984 UIP_STAT(++uip_stat.icmp.typeerr);
cassyarduino 0:e3fb1267e3c3 985 UIP_LOG("icmp: not icmp echo.");
cassyarduino 0:e3fb1267e3c3 986 goto drop;
cassyarduino 0:e3fb1267e3c3 987 }
cassyarduino 0:e3fb1267e3c3 988
cassyarduino 0:e3fb1267e3c3 989 /* If we are configured to use ping IP address assignment, we use
cassyarduino 0:e3fb1267e3c3 990 the destination IP address of this ping packet and assign it to
cassyarduino 0:e3fb1267e3c3 991 ourself. */
cassyarduino 0:e3fb1267e3c3 992 #if UIP_PINGADDRCONF
cassyarduino 0:e3fb1267e3c3 993 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
cassyarduino 0:e3fb1267e3c3 994 uip_hostaddr[0] = BUF->destipaddr[0];
cassyarduino 0:e3fb1267e3c3 995 uip_hostaddr[1] = BUF->destipaddr[1];
cassyarduino 0:e3fb1267e3c3 996 }
cassyarduino 0:e3fb1267e3c3 997 #endif /* UIP_PINGADDRCONF */
cassyarduino 0:e3fb1267e3c3 998
cassyarduino 0:e3fb1267e3c3 999 ICMPBUF->type = ICMP_ECHO_REPLY;
cassyarduino 0:e3fb1267e3c3 1000
cassyarduino 0:e3fb1267e3c3 1001 if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
cassyarduino 0:e3fb1267e3c3 1002 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
cassyarduino 0:e3fb1267e3c3 1003 } else {
cassyarduino 0:e3fb1267e3c3 1004 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
cassyarduino 0:e3fb1267e3c3 1005 }
cassyarduino 0:e3fb1267e3c3 1006
cassyarduino 0:e3fb1267e3c3 1007 /* Swap IP addresses. */
cassyarduino 0:e3fb1267e3c3 1008 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
cassyarduino 0:e3fb1267e3c3 1009 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1010
cassyarduino 0:e3fb1267e3c3 1011 UIP_STAT(++uip_stat.icmp.sent);
cassyarduino 0:e3fb1267e3c3 1012 goto send;
cassyarduino 0:e3fb1267e3c3 1013
cassyarduino 0:e3fb1267e3c3 1014 /* End of IPv4 input header processing code. */
cassyarduino 0:e3fb1267e3c3 1015 #else /* !UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1016
cassyarduino 0:e3fb1267e3c3 1017 /* This is IPv6 ICMPv6 processing code. */
cassyarduino 0:e3fb1267e3c3 1018 DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
cassyarduino 0:e3fb1267e3c3 1019
cassyarduino 0:e3fb1267e3c3 1020 if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
cassyarduino 0:e3fb1267e3c3 1021 here. */
cassyarduino 0:e3fb1267e3c3 1022 UIP_STAT(++uip_stat.ip.drop);
cassyarduino 0:e3fb1267e3c3 1023 UIP_STAT(++uip_stat.ip.protoerr);
cassyarduino 0:e3fb1267e3c3 1024 UIP_LOG("ip: neither tcp nor icmp6.");
cassyarduino 0:e3fb1267e3c3 1025 goto drop;
cassyarduino 0:e3fb1267e3c3 1026 }
cassyarduino 0:e3fb1267e3c3 1027
cassyarduino 0:e3fb1267e3c3 1028 UIP_STAT(++uip_stat.icmp.recv);
cassyarduino 0:e3fb1267e3c3 1029
cassyarduino 0:e3fb1267e3c3 1030 /* If we get a neighbor solicitation for our address we should send
cassyarduino 0:e3fb1267e3c3 1031 a neighbor advertisement message back. */
cassyarduino 0:e3fb1267e3c3 1032 if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
cassyarduino 0:e3fb1267e3c3 1033 if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
cassyarduino 0:e3fb1267e3c3 1034
cassyarduino 0:e3fb1267e3c3 1035 if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
cassyarduino 0:e3fb1267e3c3 1036 /* Save the sender's address in our neighbor list. */
cassyarduino 0:e3fb1267e3c3 1037 uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
cassyarduino 0:e3fb1267e3c3 1038 }
cassyarduino 0:e3fb1267e3c3 1039
cassyarduino 0:e3fb1267e3c3 1040 /* We should now send a neighbor advertisement back to where the
cassyarduino 0:e3fb1267e3c3 1041 neighbor solicication came from. */
cassyarduino 0:e3fb1267e3c3 1042 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
cassyarduino 0:e3fb1267e3c3 1043 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
cassyarduino 0:e3fb1267e3c3 1044
cassyarduino 0:e3fb1267e3c3 1045 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
cassyarduino 0:e3fb1267e3c3 1046
cassyarduino 0:e3fb1267e3c3 1047 uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
cassyarduino 0:e3fb1267e3c3 1048 uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1049 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
cassyarduino 0:e3fb1267e3c3 1050 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
cassyarduino 0:e3fb1267e3c3 1051 memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
cassyarduino 0:e3fb1267e3c3 1052 ICMPBUF->icmpchksum = 0;
cassyarduino 0:e3fb1267e3c3 1053 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
cassyarduino 0:e3fb1267e3c3 1054 goto send;
cassyarduino 0:e3fb1267e3c3 1055
cassyarduino 0:e3fb1267e3c3 1056 }
cassyarduino 0:e3fb1267e3c3 1057 goto drop;
cassyarduino 0:e3fb1267e3c3 1058 } else if(ICMPBUF->type == ICMP6_ECHO) {
cassyarduino 0:e3fb1267e3c3 1059 /* ICMP echo (i.e., ping) processing. This is simple, we only
cassyarduino 0:e3fb1267e3c3 1060 change the ICMP type from ECHO to ECHO_REPLY and update the
cassyarduino 0:e3fb1267e3c3 1061 ICMP checksum before we return the packet. */
cassyarduino 0:e3fb1267e3c3 1062
cassyarduino 0:e3fb1267e3c3 1063 ICMPBUF->type = ICMP6_ECHO_REPLY;
cassyarduino 0:e3fb1267e3c3 1064
cassyarduino 0:e3fb1267e3c3 1065 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
cassyarduino 0:e3fb1267e3c3 1066 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1067 ICMPBUF->icmpchksum = 0;
cassyarduino 0:e3fb1267e3c3 1068 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
cassyarduino 0:e3fb1267e3c3 1069
cassyarduino 0:e3fb1267e3c3 1070 UIP_STAT(++uip_stat.icmp.sent);
cassyarduino 0:e3fb1267e3c3 1071 goto send;
cassyarduino 0:e3fb1267e3c3 1072 } else {
cassyarduino 0:e3fb1267e3c3 1073 DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
cassyarduino 0:e3fb1267e3c3 1074 UIP_STAT(++uip_stat.icmp.drop);
cassyarduino 0:e3fb1267e3c3 1075 UIP_STAT(++uip_stat.icmp.typeerr);
cassyarduino 0:e3fb1267e3c3 1076 UIP_LOG("icmp: unknown ICMP message.");
cassyarduino 0:e3fb1267e3c3 1077 goto drop;
cassyarduino 0:e3fb1267e3c3 1078 }
cassyarduino 0:e3fb1267e3c3 1079
cassyarduino 0:e3fb1267e3c3 1080 /* End of IPv6 ICMP processing. */
cassyarduino 0:e3fb1267e3c3 1081
cassyarduino 0:e3fb1267e3c3 1082 #endif /* !UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1083
cassyarduino 0:e3fb1267e3c3 1084 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 1085 /* UDP input processing. */
cassyarduino 0:e3fb1267e3c3 1086 udp_input:
cassyarduino 0:e3fb1267e3c3 1087 /* UDP processing is really just a hack. We don't do anything to the
cassyarduino 0:e3fb1267e3c3 1088 UDP/IP headers, but let the UDP application do all the hard
cassyarduino 0:e3fb1267e3c3 1089 work. If the application sets uip_slen, it has a packet to
cassyarduino 0:e3fb1267e3c3 1090 send. */
cassyarduino 0:e3fb1267e3c3 1091 #if UIP_UDP_CHECKSUMS
cassyarduino 0:e3fb1267e3c3 1092 uip_len = uip_len - UIP_IPUDPH_LEN;
cassyarduino 0:e3fb1267e3c3 1093 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
cassyarduino 0:e3fb1267e3c3 1094 if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
cassyarduino 0:e3fb1267e3c3 1095 UIP_STAT(++uip_stat.udp.drop);
cassyarduino 0:e3fb1267e3c3 1096 UIP_STAT(++uip_stat.udp.chkerr);
cassyarduino 0:e3fb1267e3c3 1097 UIP_LOG("udp: bad checksum.");
cassyarduino 0:e3fb1267e3c3 1098 goto drop;
cassyarduino 0:e3fb1267e3c3 1099 }
cassyarduino 0:e3fb1267e3c3 1100 #else /* UIP_UDP_CHECKSUMS */
cassyarduino 0:e3fb1267e3c3 1101 uip_len = uip_len - UIP_IPUDPH_LEN;
cassyarduino 0:e3fb1267e3c3 1102 #endif /* UIP_UDP_CHECKSUMS */
cassyarduino 0:e3fb1267e3c3 1103
cassyarduino 0:e3fb1267e3c3 1104 /* Demultiplex this UDP packet between the UDP "connections". */
cassyarduino 0:e3fb1267e3c3 1105 for(uip_udp_conn = &uip_udp_conns[0];
cassyarduino 0:e3fb1267e3c3 1106 uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
cassyarduino 0:e3fb1267e3c3 1107 ++uip_udp_conn) {
cassyarduino 0:e3fb1267e3c3 1108 /* If the local UDP port is non-zero, the connection is considered
cassyarduino 0:e3fb1267e3c3 1109 to be used. If so, the local port number is checked against the
cassyarduino 0:e3fb1267e3c3 1110 destination port number in the received packet. If the two port
cassyarduino 0:e3fb1267e3c3 1111 numbers match, the remote port number is checked if the
cassyarduino 0:e3fb1267e3c3 1112 connection is bound to a remote port. Finally, if the
cassyarduino 0:e3fb1267e3c3 1113 connection is bound to a remote IP address, the source IP
cassyarduino 0:e3fb1267e3c3 1114 address of the packet is checked. */
cassyarduino 0:e3fb1267e3c3 1115 if(uip_udp_conn->lport != 0 &&
cassyarduino 0:e3fb1267e3c3 1116 UDPBUF->destport == uip_udp_conn->lport &&
cassyarduino 0:e3fb1267e3c3 1117 (uip_udp_conn->rport == 0 ||
cassyarduino 0:e3fb1267e3c3 1118 UDPBUF->srcport == uip_udp_conn->rport) &&
cassyarduino 0:e3fb1267e3c3 1119 (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
cassyarduino 0:e3fb1267e3c3 1120 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
cassyarduino 0:e3fb1267e3c3 1121 uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
cassyarduino 0:e3fb1267e3c3 1122 goto udp_found;
cassyarduino 0:e3fb1267e3c3 1123 }
cassyarduino 0:e3fb1267e3c3 1124 }
cassyarduino 0:e3fb1267e3c3 1125 UIP_LOG("udp: no matching connection found");
cassyarduino 0:e3fb1267e3c3 1126 goto drop;
cassyarduino 0:e3fb1267e3c3 1127
cassyarduino 0:e3fb1267e3c3 1128 udp_found:
cassyarduino 0:e3fb1267e3c3 1129 uip_conn = NULL;
cassyarduino 0:e3fb1267e3c3 1130 uip_flags = UIP_NEWDATA;
cassyarduino 0:e3fb1267e3c3 1131 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
cassyarduino 0:e3fb1267e3c3 1132 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1133 UIP_UDP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1134 udp_send:
cassyarduino 0:e3fb1267e3c3 1135 if(uip_slen == 0) {
cassyarduino 0:e3fb1267e3c3 1136 goto drop;
cassyarduino 0:e3fb1267e3c3 1137 }
cassyarduino 0:e3fb1267e3c3 1138 uip_len = uip_slen + UIP_IPUDPH_LEN;
cassyarduino 0:e3fb1267e3c3 1139
cassyarduino 0:e3fb1267e3c3 1140 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 1141 /* For IPv6, the IP length field does not include the IPv6 IP header
cassyarduino 0:e3fb1267e3c3 1142 length. */
cassyarduino 0:e3fb1267e3c3 1143 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
cassyarduino 0:e3fb1267e3c3 1144 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
cassyarduino 0:e3fb1267e3c3 1145 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1146 BUF->len[0] = (uip_len >> 8);
cassyarduino 0:e3fb1267e3c3 1147 BUF->len[1] = (uip_len & 0xff);
cassyarduino 0:e3fb1267e3c3 1148 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1149
cassyarduino 0:e3fb1267e3c3 1150 BUF->ttl = uip_udp_conn->ttl;
cassyarduino 0:e3fb1267e3c3 1151 BUF->proto = UIP_PROTO_UDP;
cassyarduino 0:e3fb1267e3c3 1152
cassyarduino 0:e3fb1267e3c3 1153 UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
cassyarduino 0:e3fb1267e3c3 1154 UDPBUF->udpchksum = 0;
cassyarduino 0:e3fb1267e3c3 1155
cassyarduino 0:e3fb1267e3c3 1156 BUF->srcport = uip_udp_conn->lport;
cassyarduino 0:e3fb1267e3c3 1157 BUF->destport = uip_udp_conn->rport;
cassyarduino 0:e3fb1267e3c3 1158
cassyarduino 0:e3fb1267e3c3 1159 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1160 uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
cassyarduino 0:e3fb1267e3c3 1161
cassyarduino 0:e3fb1267e3c3 1162 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
cassyarduino 0:e3fb1267e3c3 1163
cassyarduino 0:e3fb1267e3c3 1164 #if UIP_UDP_CHECKSUMS
cassyarduino 0:e3fb1267e3c3 1165 /* Calculate UDP checksum. */
cassyarduino 0:e3fb1267e3c3 1166 UDPBUF->udpchksum = ~(uip_udpchksum());
cassyarduino 0:e3fb1267e3c3 1167 if(UDPBUF->udpchksum == 0) {
cassyarduino 0:e3fb1267e3c3 1168 UDPBUF->udpchksum = 0xffff;
cassyarduino 0:e3fb1267e3c3 1169 }
cassyarduino 0:e3fb1267e3c3 1170 #endif /* UIP_UDP_CHECKSUMS */
cassyarduino 0:e3fb1267e3c3 1171
cassyarduino 0:e3fb1267e3c3 1172 goto ip_send_nolen;
cassyarduino 0:e3fb1267e3c3 1173 #endif /* UIP_UDP */
cassyarduino 0:e3fb1267e3c3 1174
cassyarduino 0:e3fb1267e3c3 1175 /* TCP input processing. */
cassyarduino 0:e3fb1267e3c3 1176 tcp_input:
cassyarduino 0:e3fb1267e3c3 1177 UIP_STAT(++uip_stat.tcp.recv);
cassyarduino 0:e3fb1267e3c3 1178
cassyarduino 0:e3fb1267e3c3 1179 /* Start of TCP input header processing code. */
cassyarduino 0:e3fb1267e3c3 1180
cassyarduino 0:e3fb1267e3c3 1181 if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
cassyarduino 0:e3fb1267e3c3 1182 checksum. */
cassyarduino 0:e3fb1267e3c3 1183 UIP_STAT(++uip_stat.tcp.drop);
cassyarduino 0:e3fb1267e3c3 1184 UIP_STAT(++uip_stat.tcp.chkerr);
cassyarduino 0:e3fb1267e3c3 1185 UIP_LOG("tcp: bad checksum.");
cassyarduino 0:e3fb1267e3c3 1186 goto drop;
cassyarduino 0:e3fb1267e3c3 1187 }
cassyarduino 0:e3fb1267e3c3 1188
cassyarduino 0:e3fb1267e3c3 1189
cassyarduino 0:e3fb1267e3c3 1190 /* Demultiplex this segment. */
cassyarduino 0:e3fb1267e3c3 1191 /* First check any active connections. */
cassyarduino 0:e3fb1267e3c3 1192 for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
cassyarduino 0:e3fb1267e3c3 1193 ++uip_connr) {
cassyarduino 0:e3fb1267e3c3 1194 if(uip_connr->tcpstateflags != UIP_CLOSED &&
cassyarduino 0:e3fb1267e3c3 1195 BUF->destport == uip_connr->lport &&
cassyarduino 0:e3fb1267e3c3 1196 BUF->srcport == uip_connr->rport &&
cassyarduino 0:e3fb1267e3c3 1197 uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
cassyarduino 0:e3fb1267e3c3 1198 goto found;
cassyarduino 0:e3fb1267e3c3 1199 }
cassyarduino 0:e3fb1267e3c3 1200 }
cassyarduino 0:e3fb1267e3c3 1201
cassyarduino 0:e3fb1267e3c3 1202 /* If we didn't find and active connection that expected the packet,
cassyarduino 0:e3fb1267e3c3 1203 either this packet is an old duplicate, or this is a SYN packet
cassyarduino 0:e3fb1267e3c3 1204 destined for a connection in LISTEN. If the SYN flag isn't set,
cassyarduino 0:e3fb1267e3c3 1205 it is an old packet and we send a RST. */
cassyarduino 0:e3fb1267e3c3 1206 if((BUF->flags & TCP_CTL) != TCP_SYN) {
cassyarduino 0:e3fb1267e3c3 1207 goto reset;
cassyarduino 0:e3fb1267e3c3 1208 }
cassyarduino 0:e3fb1267e3c3 1209
cassyarduino 0:e3fb1267e3c3 1210 tmp16 = BUF->destport;
cassyarduino 0:e3fb1267e3c3 1211 /* Next, check listening connections. */
cassyarduino 0:e3fb1267e3c3 1212 for(c = 0; c < UIP_LISTENPORTS; ++c) {
cassyarduino 0:e3fb1267e3c3 1213 if(tmp16 == uip_listenports[c])
cassyarduino 0:e3fb1267e3c3 1214 goto found_listen;
cassyarduino 0:e3fb1267e3c3 1215 }
cassyarduino 0:e3fb1267e3c3 1216
cassyarduino 0:e3fb1267e3c3 1217 /* No matching connection found, so we send a RST packet. */
cassyarduino 0:e3fb1267e3c3 1218 UIP_STAT(++uip_stat.tcp.synrst);
cassyarduino 0:e3fb1267e3c3 1219 reset:
cassyarduino 0:e3fb1267e3c3 1220
cassyarduino 0:e3fb1267e3c3 1221 /* We do not send resets in response to resets. */
cassyarduino 0:e3fb1267e3c3 1222 if(BUF->flags & TCP_RST) {
cassyarduino 0:e3fb1267e3c3 1223 goto drop;
cassyarduino 0:e3fb1267e3c3 1224 }
cassyarduino 0:e3fb1267e3c3 1225
cassyarduino 0:e3fb1267e3c3 1226 UIP_STAT(++uip_stat.tcp.rst);
cassyarduino 0:e3fb1267e3c3 1227
cassyarduino 0:e3fb1267e3c3 1228 BUF->flags = TCP_RST | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1229 uip_len = UIP_IPTCPH_LEN;
cassyarduino 0:e3fb1267e3c3 1230 BUF->tcpoffset = 5 << 4;
cassyarduino 0:e3fb1267e3c3 1231
cassyarduino 0:e3fb1267e3c3 1232 /* Flip the seqno and ackno fields in the TCP header. */
cassyarduino 0:e3fb1267e3c3 1233 c = BUF->seqno[3];
cassyarduino 0:e3fb1267e3c3 1234 BUF->seqno[3] = BUF->ackno[3];
cassyarduino 0:e3fb1267e3c3 1235 BUF->ackno[3] = c;
cassyarduino 0:e3fb1267e3c3 1236
cassyarduino 0:e3fb1267e3c3 1237 c = BUF->seqno[2];
cassyarduino 0:e3fb1267e3c3 1238 BUF->seqno[2] = BUF->ackno[2];
cassyarduino 0:e3fb1267e3c3 1239 BUF->ackno[2] = c;
cassyarduino 0:e3fb1267e3c3 1240
cassyarduino 0:e3fb1267e3c3 1241 c = BUF->seqno[1];
cassyarduino 0:e3fb1267e3c3 1242 BUF->seqno[1] = BUF->ackno[1];
cassyarduino 0:e3fb1267e3c3 1243 BUF->ackno[1] = c;
cassyarduino 0:e3fb1267e3c3 1244
cassyarduino 0:e3fb1267e3c3 1245 c = BUF->seqno[0];
cassyarduino 0:e3fb1267e3c3 1246 BUF->seqno[0] = BUF->ackno[0];
cassyarduino 0:e3fb1267e3c3 1247 BUF->ackno[0] = c;
cassyarduino 0:e3fb1267e3c3 1248
cassyarduino 0:e3fb1267e3c3 1249 /* We also have to increase the sequence number we are
cassyarduino 0:e3fb1267e3c3 1250 acknowledging. If the least significant byte overflowed, we need
cassyarduino 0:e3fb1267e3c3 1251 to propagate the carry to the other bytes as well. */
cassyarduino 0:e3fb1267e3c3 1252 if(++BUF->ackno[3] == 0) {
cassyarduino 0:e3fb1267e3c3 1253 if(++BUF->ackno[2] == 0) {
cassyarduino 0:e3fb1267e3c3 1254 if(++BUF->ackno[1] == 0) {
cassyarduino 0:e3fb1267e3c3 1255 ++BUF->ackno[0];
cassyarduino 0:e3fb1267e3c3 1256 }
cassyarduino 0:e3fb1267e3c3 1257 }
cassyarduino 0:e3fb1267e3c3 1258 }
cassyarduino 0:e3fb1267e3c3 1259
cassyarduino 0:e3fb1267e3c3 1260 /* Swap port numbers. */
cassyarduino 0:e3fb1267e3c3 1261 tmp16 = BUF->srcport;
cassyarduino 0:e3fb1267e3c3 1262 BUF->srcport = BUF->destport;
cassyarduino 0:e3fb1267e3c3 1263 BUF->destport = tmp16;
cassyarduino 0:e3fb1267e3c3 1264
cassyarduino 0:e3fb1267e3c3 1265 /* Swap IP addresses. */
cassyarduino 0:e3fb1267e3c3 1266 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
cassyarduino 0:e3fb1267e3c3 1267 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1268
cassyarduino 0:e3fb1267e3c3 1269 /* And send out the RST packet! */
cassyarduino 0:e3fb1267e3c3 1270 goto tcp_send_noconn;
cassyarduino 0:e3fb1267e3c3 1271
cassyarduino 0:e3fb1267e3c3 1272 /* This label will be jumped to if we matched the incoming packet
cassyarduino 0:e3fb1267e3c3 1273 with a connection in LISTEN. In that case, we should create a new
cassyarduino 0:e3fb1267e3c3 1274 connection and send a SYNACK in return. */
cassyarduino 0:e3fb1267e3c3 1275 found_listen:
cassyarduino 0:e3fb1267e3c3 1276 /* First we check if there are any connections avaliable. Unused
cassyarduino 0:e3fb1267e3c3 1277 connections are kept in the same table as used connections, but
cassyarduino 0:e3fb1267e3c3 1278 unused ones have the tcpstate set to CLOSED. Also, connections in
cassyarduino 0:e3fb1267e3c3 1279 TIME_WAIT are kept track of and we'll use the oldest one if no
cassyarduino 0:e3fb1267e3c3 1280 CLOSED connections are found. Thanks to Eddie C. Dost for a very
cassyarduino 0:e3fb1267e3c3 1281 nice algorithm for the TIME_WAIT search. */
cassyarduino 0:e3fb1267e3c3 1282 uip_connr = 0;
cassyarduino 0:e3fb1267e3c3 1283 for(c = 0; c < UIP_CONNS; ++c) {
cassyarduino 0:e3fb1267e3c3 1284 if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
cassyarduino 0:e3fb1267e3c3 1285 uip_connr = &uip_conns[c];
cassyarduino 0:e3fb1267e3c3 1286 break;
cassyarduino 0:e3fb1267e3c3 1287 }
cassyarduino 0:e3fb1267e3c3 1288 if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
cassyarduino 0:e3fb1267e3c3 1289 if(uip_connr == 0 ||
cassyarduino 0:e3fb1267e3c3 1290 uip_conns[c].timer > uip_connr->timer) {
cassyarduino 0:e3fb1267e3c3 1291 uip_connr = &uip_conns[c];
cassyarduino 0:e3fb1267e3c3 1292 }
cassyarduino 0:e3fb1267e3c3 1293 }
cassyarduino 0:e3fb1267e3c3 1294 }
cassyarduino 0:e3fb1267e3c3 1295
cassyarduino 0:e3fb1267e3c3 1296 if(uip_connr == 0) {
cassyarduino 0:e3fb1267e3c3 1297 /* All connections are used already, we drop packet and hope that
cassyarduino 0:e3fb1267e3c3 1298 the remote end will retransmit the packet at a time when we
cassyarduino 0:e3fb1267e3c3 1299 have more spare connections. */
cassyarduino 0:e3fb1267e3c3 1300 UIP_STAT(++uip_stat.tcp.syndrop);
cassyarduino 0:e3fb1267e3c3 1301 UIP_LOG("tcp: found no unused connections.");
cassyarduino 0:e3fb1267e3c3 1302 goto drop;
cassyarduino 0:e3fb1267e3c3 1303 }
cassyarduino 0:e3fb1267e3c3 1304 uip_conn = uip_connr;
cassyarduino 0:e3fb1267e3c3 1305
cassyarduino 0:e3fb1267e3c3 1306 /* Fill in the necessary fields for the new connection. */
cassyarduino 0:e3fb1267e3c3 1307 uip_connr->rto = uip_connr->timer = UIP_RTO;
cassyarduino 0:e3fb1267e3c3 1308 uip_connr->sa = 0;
cassyarduino 0:e3fb1267e3c3 1309 uip_connr->sv = 4;
cassyarduino 0:e3fb1267e3c3 1310 uip_connr->nrtx = 0;
cassyarduino 0:e3fb1267e3c3 1311 uip_connr->lport = BUF->destport;
cassyarduino 0:e3fb1267e3c3 1312 uip_connr->rport = BUF->srcport;
cassyarduino 0:e3fb1267e3c3 1313 uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
cassyarduino 0:e3fb1267e3c3 1314 uip_connr->tcpstateflags = UIP_SYN_RCVD;
cassyarduino 0:e3fb1267e3c3 1315
cassyarduino 0:e3fb1267e3c3 1316 uip_connr->snd_nxt[0] = iss[0];
cassyarduino 0:e3fb1267e3c3 1317 uip_connr->snd_nxt[1] = iss[1];
cassyarduino 0:e3fb1267e3c3 1318 uip_connr->snd_nxt[2] = iss[2];
cassyarduino 0:e3fb1267e3c3 1319 uip_connr->snd_nxt[3] = iss[3];
cassyarduino 0:e3fb1267e3c3 1320 uip_connr->len = 1;
cassyarduino 0:e3fb1267e3c3 1321
cassyarduino 0:e3fb1267e3c3 1322 /* rcv_nxt should be the seqno from the incoming packet + 1. */
cassyarduino 0:e3fb1267e3c3 1323 uip_connr->rcv_nxt[3] = BUF->seqno[3];
cassyarduino 0:e3fb1267e3c3 1324 uip_connr->rcv_nxt[2] = BUF->seqno[2];
cassyarduino 0:e3fb1267e3c3 1325 uip_connr->rcv_nxt[1] = BUF->seqno[1];
cassyarduino 0:e3fb1267e3c3 1326 uip_connr->rcv_nxt[0] = BUF->seqno[0];
cassyarduino 0:e3fb1267e3c3 1327 uip_add_rcv_nxt(1);
cassyarduino 0:e3fb1267e3c3 1328
cassyarduino 0:e3fb1267e3c3 1329 /* Parse the TCP MSS option, if present. */
cassyarduino 0:e3fb1267e3c3 1330 if((BUF->tcpoffset & 0xf0) > 0x50) {
cassyarduino 0:e3fb1267e3c3 1331 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
cassyarduino 0:e3fb1267e3c3 1332 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
cassyarduino 0:e3fb1267e3c3 1333 if(opt == TCP_OPT_END) {
cassyarduino 0:e3fb1267e3c3 1334 /* End of options. */
cassyarduino 0:e3fb1267e3c3 1335 break;
cassyarduino 0:e3fb1267e3c3 1336 } else if(opt == TCP_OPT_NOOP) {
cassyarduino 0:e3fb1267e3c3 1337 ++c;
cassyarduino 0:e3fb1267e3c3 1338 /* NOP option. */
cassyarduino 0:e3fb1267e3c3 1339 } else if(opt == TCP_OPT_MSS &&
cassyarduino 0:e3fb1267e3c3 1340 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
cassyarduino 0:e3fb1267e3c3 1341 /* An MSS option with the right option length. */
cassyarduino 0:e3fb1267e3c3 1342 tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
cassyarduino 0:e3fb1267e3c3 1343 (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
cassyarduino 0:e3fb1267e3c3 1344 uip_connr->initialmss = uip_connr->mss =
cassyarduino 0:e3fb1267e3c3 1345 tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
cassyarduino 0:e3fb1267e3c3 1346
cassyarduino 0:e3fb1267e3c3 1347 /* And we are done processing options. */
cassyarduino 0:e3fb1267e3c3 1348 break;
cassyarduino 0:e3fb1267e3c3 1349 } else {
cassyarduino 0:e3fb1267e3c3 1350 /* All other options have a length field, so that we easily
cassyarduino 0:e3fb1267e3c3 1351 can skip past them. */
cassyarduino 0:e3fb1267e3c3 1352 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
cassyarduino 0:e3fb1267e3c3 1353 /* If the length field is zero, the options are malformed
cassyarduino 0:e3fb1267e3c3 1354 and we don't process them further. */
cassyarduino 0:e3fb1267e3c3 1355 break;
cassyarduino 0:e3fb1267e3c3 1356 }
cassyarduino 0:e3fb1267e3c3 1357 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
cassyarduino 0:e3fb1267e3c3 1358 }
cassyarduino 0:e3fb1267e3c3 1359 }
cassyarduino 0:e3fb1267e3c3 1360 }
cassyarduino 0:e3fb1267e3c3 1361
cassyarduino 0:e3fb1267e3c3 1362 /* Our response will be a SYNACK. */
cassyarduino 0:e3fb1267e3c3 1363 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 1364 tcp_send_synack:
cassyarduino 0:e3fb1267e3c3 1365 BUF->flags = TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1366
cassyarduino 0:e3fb1267e3c3 1367 tcp_send_syn:
cassyarduino 0:e3fb1267e3c3 1368 BUF->flags |= TCP_SYN;
cassyarduino 0:e3fb1267e3c3 1369 #else /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 1370 tcp_send_synack:
cassyarduino 0:e3fb1267e3c3 1371 BUF->flags = TCP_SYN | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1372 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 1373
cassyarduino 0:e3fb1267e3c3 1374 /* We send out the TCP Maximum Segment Size option with our
cassyarduino 0:e3fb1267e3c3 1375 SYNACK. */
cassyarduino 0:e3fb1267e3c3 1376 BUF->optdata[0] = TCP_OPT_MSS;
cassyarduino 0:e3fb1267e3c3 1377 BUF->optdata[1] = TCP_OPT_MSS_LEN;
cassyarduino 0:e3fb1267e3c3 1378 BUF->optdata[2] = (UIP_TCP_MSS) / 256;
cassyarduino 0:e3fb1267e3c3 1379 BUF->optdata[3] = (UIP_TCP_MSS) & 255;
cassyarduino 0:e3fb1267e3c3 1380 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
cassyarduino 0:e3fb1267e3c3 1381 BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
cassyarduino 0:e3fb1267e3c3 1382 goto tcp_send;
cassyarduino 0:e3fb1267e3c3 1383
cassyarduino 0:e3fb1267e3c3 1384 /* This label will be jumped to if we found an active connection. */
cassyarduino 0:e3fb1267e3c3 1385 found:
cassyarduino 0:e3fb1267e3c3 1386 uip_conn = uip_connr;
cassyarduino 0:e3fb1267e3c3 1387 uip_flags = 0;
cassyarduino 0:e3fb1267e3c3 1388 /* We do a very naive form of TCP reset processing; we just accept
cassyarduino 0:e3fb1267e3c3 1389 any RST and kill our connection. We should in fact check if the
cassyarduino 0:e3fb1267e3c3 1390 sequence number of this reset is wihtin our advertised window
cassyarduino 0:e3fb1267e3c3 1391 before we accept the reset. */
cassyarduino 0:e3fb1267e3c3 1392 if(BUF->flags & TCP_RST) {
cassyarduino 0:e3fb1267e3c3 1393 uip_connr->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 1394 UIP_LOG("tcp: got reset, aborting connection.");
cassyarduino 0:e3fb1267e3c3 1395 uip_flags = UIP_ABORT;
cassyarduino 0:e3fb1267e3c3 1396 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1397 goto drop;
cassyarduino 0:e3fb1267e3c3 1398 }
cassyarduino 0:e3fb1267e3c3 1399 /* Calculated the length of the data, if the application has sent
cassyarduino 0:e3fb1267e3c3 1400 any data to us. */
cassyarduino 0:e3fb1267e3c3 1401 c = (BUF->tcpoffset >> 4) << 2;
cassyarduino 0:e3fb1267e3c3 1402 /* uip_len will contain the length of the actual TCP data. This is
cassyarduino 0:e3fb1267e3c3 1403 calculated by subtracing the length of the TCP header (in
cassyarduino 0:e3fb1267e3c3 1404 c) and the length of the IP header (20 bytes). */
cassyarduino 0:e3fb1267e3c3 1405 uip_len = uip_len - c - UIP_IPH_LEN;
cassyarduino 0:e3fb1267e3c3 1406
cassyarduino 0:e3fb1267e3c3 1407 /* First, check if the sequence number of the incoming packet is
cassyarduino 0:e3fb1267e3c3 1408 what we're expecting next. If not, we send out an ACK with the
cassyarduino 0:e3fb1267e3c3 1409 correct numbers in. */
cassyarduino 0:e3fb1267e3c3 1410 if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
cassyarduino 0:e3fb1267e3c3 1411 ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
cassyarduino 0:e3fb1267e3c3 1412 if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
cassyarduino 0:e3fb1267e3c3 1413 (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
cassyarduino 0:e3fb1267e3c3 1414 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
cassyarduino 0:e3fb1267e3c3 1415 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
cassyarduino 0:e3fb1267e3c3 1416 BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
cassyarduino 0:e3fb1267e3c3 1417 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1418 }
cassyarduino 0:e3fb1267e3c3 1419 }
cassyarduino 0:e3fb1267e3c3 1420
cassyarduino 0:e3fb1267e3c3 1421 /* Next, check if the incoming segment acknowledges any outstanding
cassyarduino 0:e3fb1267e3c3 1422 data. If so, we update the sequence number, reset the length of
cassyarduino 0:e3fb1267e3c3 1423 the outstanding data, calculate RTT estimations, and reset the
cassyarduino 0:e3fb1267e3c3 1424 retransmission timer. */
cassyarduino 0:e3fb1267e3c3 1425 if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
cassyarduino 0:e3fb1267e3c3 1426 uip_add32(uip_connr->snd_nxt, uip_connr->len);
cassyarduino 0:e3fb1267e3c3 1427
cassyarduino 0:e3fb1267e3c3 1428 if(BUF->ackno[0] == uip_acc32[0] &&
cassyarduino 0:e3fb1267e3c3 1429 BUF->ackno[1] == uip_acc32[1] &&
cassyarduino 0:e3fb1267e3c3 1430 BUF->ackno[2] == uip_acc32[2] &&
cassyarduino 0:e3fb1267e3c3 1431 BUF->ackno[3] == uip_acc32[3]) {
cassyarduino 0:e3fb1267e3c3 1432 /* Update sequence number. */
cassyarduino 0:e3fb1267e3c3 1433 uip_connr->snd_nxt[0] = uip_acc32[0];
cassyarduino 0:e3fb1267e3c3 1434 uip_connr->snd_nxt[1] = uip_acc32[1];
cassyarduino 0:e3fb1267e3c3 1435 uip_connr->snd_nxt[2] = uip_acc32[2];
cassyarduino 0:e3fb1267e3c3 1436 uip_connr->snd_nxt[3] = uip_acc32[3];
cassyarduino 0:e3fb1267e3c3 1437
cassyarduino 0:e3fb1267e3c3 1438
cassyarduino 0:e3fb1267e3c3 1439 /* Do RTT estimation, unless we have done retransmissions. */
cassyarduino 0:e3fb1267e3c3 1440 if(uip_connr->nrtx == 0) {
cassyarduino 0:e3fb1267e3c3 1441 signed char m;
cassyarduino 0:e3fb1267e3c3 1442 m = uip_connr->rto - uip_connr->timer;
cassyarduino 0:e3fb1267e3c3 1443 /* This is taken directly from VJs original code in his paper */
cassyarduino 0:e3fb1267e3c3 1444 m = m - (uip_connr->sa >> 3);
cassyarduino 0:e3fb1267e3c3 1445 uip_connr->sa += m;
cassyarduino 0:e3fb1267e3c3 1446 if(m < 0) {
cassyarduino 0:e3fb1267e3c3 1447 m = -m;
cassyarduino 0:e3fb1267e3c3 1448 }
cassyarduino 0:e3fb1267e3c3 1449 m = m - (uip_connr->sv >> 2);
cassyarduino 0:e3fb1267e3c3 1450 uip_connr->sv += m;
cassyarduino 0:e3fb1267e3c3 1451 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
cassyarduino 0:e3fb1267e3c3 1452
cassyarduino 0:e3fb1267e3c3 1453 }
cassyarduino 0:e3fb1267e3c3 1454 /* Set the acknowledged flag. */
cassyarduino 0:e3fb1267e3c3 1455 uip_flags = UIP_ACKDATA;
cassyarduino 0:e3fb1267e3c3 1456 /* Reset the retransmission timer. */
cassyarduino 0:e3fb1267e3c3 1457 uip_connr->timer = uip_connr->rto;
cassyarduino 0:e3fb1267e3c3 1458
cassyarduino 0:e3fb1267e3c3 1459 /* Reset length of outstanding data. */
cassyarduino 0:e3fb1267e3c3 1460 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1461 }
cassyarduino 0:e3fb1267e3c3 1462
cassyarduino 0:e3fb1267e3c3 1463 }
cassyarduino 0:e3fb1267e3c3 1464
cassyarduino 0:e3fb1267e3c3 1465 /* Do different things depending on in what state the connection is. */
cassyarduino 0:e3fb1267e3c3 1466 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
cassyarduino 0:e3fb1267e3c3 1467 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
cassyarduino 0:e3fb1267e3c3 1468 implemented, since we force the application to close when the
cassyarduino 0:e3fb1267e3c3 1469 peer sends a FIN (hence the application goes directly from
cassyarduino 0:e3fb1267e3c3 1470 ESTABLISHED to LAST_ACK). */
cassyarduino 0:e3fb1267e3c3 1471 case UIP_SYN_RCVD:
cassyarduino 0:e3fb1267e3c3 1472 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
cassyarduino 0:e3fb1267e3c3 1473 we are waiting for an ACK that acknowledges the data we sent
cassyarduino 0:e3fb1267e3c3 1474 out the last time. Therefore, we want to have the UIP_ACKDATA
cassyarduino 0:e3fb1267e3c3 1475 flag set. If so, we enter the ESTABLISHED state. */
cassyarduino 0:e3fb1267e3c3 1476 if(uip_flags & UIP_ACKDATA) {
cassyarduino 0:e3fb1267e3c3 1477 uip_connr->tcpstateflags = UIP_ESTABLISHED;
cassyarduino 0:e3fb1267e3c3 1478 uip_flags = UIP_CONNECTED;
cassyarduino 0:e3fb1267e3c3 1479 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1480 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1481 uip_flags |= UIP_NEWDATA;
cassyarduino 0:e3fb1267e3c3 1482 uip_add_rcv_nxt(uip_len);
cassyarduino 0:e3fb1267e3c3 1483 }
cassyarduino 0:e3fb1267e3c3 1484 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1485 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1486 goto appsend;
cassyarduino 0:e3fb1267e3c3 1487 }
cassyarduino 0:e3fb1267e3c3 1488 goto drop;
cassyarduino 0:e3fb1267e3c3 1489 #if UIP_ACTIVE_OPEN
cassyarduino 0:e3fb1267e3c3 1490 case UIP_SYN_SENT:
cassyarduino 0:e3fb1267e3c3 1491 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
cassyarduino 0:e3fb1267e3c3 1492 our SYN. The rcv_nxt is set to sequence number in the SYNACK
cassyarduino 0:e3fb1267e3c3 1493 plus one, and we send an ACK. We move into the ESTABLISHED
cassyarduino 0:e3fb1267e3c3 1494 state. */
cassyarduino 0:e3fb1267e3c3 1495 if((uip_flags & UIP_ACKDATA) &&
cassyarduino 0:e3fb1267e3c3 1496 (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
cassyarduino 0:e3fb1267e3c3 1497
cassyarduino 0:e3fb1267e3c3 1498 /* Parse the TCP MSS option, if present. */
cassyarduino 0:e3fb1267e3c3 1499 if((BUF->tcpoffset & 0xf0) > 0x50) {
cassyarduino 0:e3fb1267e3c3 1500 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
cassyarduino 0:e3fb1267e3c3 1501 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
cassyarduino 0:e3fb1267e3c3 1502 if(opt == TCP_OPT_END) {
cassyarduino 0:e3fb1267e3c3 1503 /* End of options. */
cassyarduino 0:e3fb1267e3c3 1504 break;
cassyarduino 0:e3fb1267e3c3 1505 } else if(opt == TCP_OPT_NOOP) {
cassyarduino 0:e3fb1267e3c3 1506 ++c;
cassyarduino 0:e3fb1267e3c3 1507 /* NOP option. */
cassyarduino 0:e3fb1267e3c3 1508 } else if(opt == TCP_OPT_MSS &&
cassyarduino 0:e3fb1267e3c3 1509 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
cassyarduino 0:e3fb1267e3c3 1510 /* An MSS option with the right option length. */
cassyarduino 0:e3fb1267e3c3 1511 tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
cassyarduino 0:e3fb1267e3c3 1512 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
cassyarduino 0:e3fb1267e3c3 1513 uip_connr->initialmss =
cassyarduino 0:e3fb1267e3c3 1514 uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
cassyarduino 0:e3fb1267e3c3 1515
cassyarduino 0:e3fb1267e3c3 1516 /* And we are done processing options. */
cassyarduino 0:e3fb1267e3c3 1517 break;
cassyarduino 0:e3fb1267e3c3 1518 } else {
cassyarduino 0:e3fb1267e3c3 1519 /* All other options have a length field, so that we easily
cassyarduino 0:e3fb1267e3c3 1520 can skip past them. */
cassyarduino 0:e3fb1267e3c3 1521 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
cassyarduino 0:e3fb1267e3c3 1522 /* If the length field is zero, the options are malformed
cassyarduino 0:e3fb1267e3c3 1523 and we don't process them further. */
cassyarduino 0:e3fb1267e3c3 1524 break;
cassyarduino 0:e3fb1267e3c3 1525 }
cassyarduino 0:e3fb1267e3c3 1526 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
cassyarduino 0:e3fb1267e3c3 1527 }
cassyarduino 0:e3fb1267e3c3 1528 }
cassyarduino 0:e3fb1267e3c3 1529 }
cassyarduino 0:e3fb1267e3c3 1530 uip_connr->tcpstateflags = UIP_ESTABLISHED;
cassyarduino 0:e3fb1267e3c3 1531 uip_connr->rcv_nxt[0] = BUF->seqno[0];
cassyarduino 0:e3fb1267e3c3 1532 uip_connr->rcv_nxt[1] = BUF->seqno[1];
cassyarduino 0:e3fb1267e3c3 1533 uip_connr->rcv_nxt[2] = BUF->seqno[2];
cassyarduino 0:e3fb1267e3c3 1534 uip_connr->rcv_nxt[3] = BUF->seqno[3];
cassyarduino 0:e3fb1267e3c3 1535 uip_add_rcv_nxt(1);
cassyarduino 0:e3fb1267e3c3 1536 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
cassyarduino 0:e3fb1267e3c3 1537 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1538 uip_len = 0;
cassyarduino 0:e3fb1267e3c3 1539 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1540 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1541 goto appsend;
cassyarduino 0:e3fb1267e3c3 1542 }
cassyarduino 0:e3fb1267e3c3 1543 /* Inform the application that the connection failed */
cassyarduino 0:e3fb1267e3c3 1544 uip_flags = UIP_ABORT;
cassyarduino 0:e3fb1267e3c3 1545 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1546 /* The connection is closed after we send the RST */
cassyarduino 0:e3fb1267e3c3 1547 uip_conn->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 1548 goto reset;
cassyarduino 0:e3fb1267e3c3 1549 #endif /* UIP_ACTIVE_OPEN */
cassyarduino 0:e3fb1267e3c3 1550
cassyarduino 0:e3fb1267e3c3 1551 case UIP_ESTABLISHED:
cassyarduino 0:e3fb1267e3c3 1552 /* In the ESTABLISHED state, we call upon the application to feed
cassyarduino 0:e3fb1267e3c3 1553 data into the uip_buf. If the UIP_ACKDATA flag is set, the
cassyarduino 0:e3fb1267e3c3 1554 application should put new data into the buffer, otherwise we are
cassyarduino 0:e3fb1267e3c3 1555 retransmitting an old segment, and the application should put that
cassyarduino 0:e3fb1267e3c3 1556 data into the buffer.
cassyarduino 0:e3fb1267e3c3 1557
cassyarduino 0:e3fb1267e3c3 1558 If the incoming packet is a FIN, we should close the connection on
cassyarduino 0:e3fb1267e3c3 1559 this side as well, and we send out a FIN and enter the LAST_ACK
cassyarduino 0:e3fb1267e3c3 1560 state. We require that there is no outstanding data; otherwise the
cassyarduino 0:e3fb1267e3c3 1561 sequence numbers will be screwed up. */
cassyarduino 0:e3fb1267e3c3 1562
cassyarduino 0:e3fb1267e3c3 1563 if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
cassyarduino 0:e3fb1267e3c3 1564 if(uip_outstanding(uip_connr)) {
cassyarduino 0:e3fb1267e3c3 1565 goto drop;
cassyarduino 0:e3fb1267e3c3 1566 }
cassyarduino 0:e3fb1267e3c3 1567 uip_add_rcv_nxt(1 + uip_len);
cassyarduino 0:e3fb1267e3c3 1568 uip_flags |= UIP_CLOSE;
cassyarduino 0:e3fb1267e3c3 1569 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1570 uip_flags |= UIP_NEWDATA;
cassyarduino 0:e3fb1267e3c3 1571 }
cassyarduino 0:e3fb1267e3c3 1572 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1573 uip_connr->len = 1;
cassyarduino 0:e3fb1267e3c3 1574 uip_connr->tcpstateflags = UIP_LAST_ACK;
cassyarduino 0:e3fb1267e3c3 1575 uip_connr->nrtx = 0;
cassyarduino 0:e3fb1267e3c3 1576 tcp_send_finack:
cassyarduino 0:e3fb1267e3c3 1577 BUF->flags = TCP_FIN | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1578 goto tcp_send_nodata;
cassyarduino 0:e3fb1267e3c3 1579 }
cassyarduino 0:e3fb1267e3c3 1580
cassyarduino 0:e3fb1267e3c3 1581 /* Check the URG flag. If this is set, the segment carries urgent
cassyarduino 0:e3fb1267e3c3 1582 data that we must pass to the application. */
cassyarduino 0:e3fb1267e3c3 1583 if((BUF->flags & TCP_URG) != 0) {
cassyarduino 0:e3fb1267e3c3 1584 #if UIP_URGDATA > 0
cassyarduino 0:e3fb1267e3c3 1585 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
cassyarduino 0:e3fb1267e3c3 1586 if(uip_urglen > uip_len) {
cassyarduino 0:e3fb1267e3c3 1587 /* There is more urgent data in the next segment to come. */
cassyarduino 0:e3fb1267e3c3 1588 uip_urglen = uip_len;
cassyarduino 0:e3fb1267e3c3 1589 }
cassyarduino 0:e3fb1267e3c3 1590 uip_add_rcv_nxt(uip_urglen);
cassyarduino 0:e3fb1267e3c3 1591 uip_len -= uip_urglen;
cassyarduino 0:e3fb1267e3c3 1592 uip_urgdata = uip_appdata;
cassyarduino 0:e3fb1267e3c3 1593 uip_appdata += uip_urglen;
cassyarduino 0:e3fb1267e3c3 1594 } else {
cassyarduino 0:e3fb1267e3c3 1595 uip_urglen = 0;
cassyarduino 0:e3fb1267e3c3 1596 #else /* UIP_URGDATA > 0 */
cassyarduino 0:e3fb1267e3c3 1597 uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
cassyarduino 0:e3fb1267e3c3 1598 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
cassyarduino 0:e3fb1267e3c3 1599 #endif /* UIP_URGDATA > 0 */
cassyarduino 0:e3fb1267e3c3 1600 }
cassyarduino 0:e3fb1267e3c3 1601
cassyarduino 0:e3fb1267e3c3 1602 /* If uip_len > 0 we have TCP data in the packet, and we flag this
cassyarduino 0:e3fb1267e3c3 1603 by setting the UIP_NEWDATA flag and update the sequence number
cassyarduino 0:e3fb1267e3c3 1604 we acknowledge. If the application has stopped the dataflow
cassyarduino 0:e3fb1267e3c3 1605 using uip_stop(), we must not accept any data packets from the
cassyarduino 0:e3fb1267e3c3 1606 remote host. */
cassyarduino 0:e3fb1267e3c3 1607 if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
cassyarduino 0:e3fb1267e3c3 1608 uip_flags |= UIP_NEWDATA;
cassyarduino 0:e3fb1267e3c3 1609 uip_add_rcv_nxt(uip_len);
cassyarduino 0:e3fb1267e3c3 1610 }
cassyarduino 0:e3fb1267e3c3 1611
cassyarduino 0:e3fb1267e3c3 1612 /* Check if the available buffer space advertised by the other end
cassyarduino 0:e3fb1267e3c3 1613 is smaller than the initial MSS for this connection. If so, we
cassyarduino 0:e3fb1267e3c3 1614 set the current MSS to the window size to ensure that the
cassyarduino 0:e3fb1267e3c3 1615 application does not send more data than the other end can
cassyarduino 0:e3fb1267e3c3 1616 handle.
cassyarduino 0:e3fb1267e3c3 1617
cassyarduino 0:e3fb1267e3c3 1618 If the remote host advertises a zero window, we set the MSS to
cassyarduino 0:e3fb1267e3c3 1619 the initial MSS so that the application will send an entire MSS
cassyarduino 0:e3fb1267e3c3 1620 of data. This data will not be acknowledged by the receiver,
cassyarduino 0:e3fb1267e3c3 1621 and the application will retransmit it. This is called the
cassyarduino 0:e3fb1267e3c3 1622 "persistent timer" and uses the retransmission mechanim.
cassyarduino 0:e3fb1267e3c3 1623 */
cassyarduino 0:e3fb1267e3c3 1624 tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
cassyarduino 0:e3fb1267e3c3 1625 if(tmp16 > uip_connr->initialmss ||
cassyarduino 0:e3fb1267e3c3 1626 tmp16 == 0) {
cassyarduino 0:e3fb1267e3c3 1627 tmp16 = uip_connr->initialmss;
cassyarduino 0:e3fb1267e3c3 1628 }
cassyarduino 0:e3fb1267e3c3 1629 uip_connr->mss = tmp16;
cassyarduino 0:e3fb1267e3c3 1630
cassyarduino 0:e3fb1267e3c3 1631 /* If this packet constitutes an ACK for outstanding data (flagged
cassyarduino 0:e3fb1267e3c3 1632 by the UIP_ACKDATA flag, we should call the application since it
cassyarduino 0:e3fb1267e3c3 1633 might want to send more data. If the incoming packet had data
cassyarduino 0:e3fb1267e3c3 1634 from the peer (as flagged by the UIP_NEWDATA flag), the
cassyarduino 0:e3fb1267e3c3 1635 application must also be notified.
cassyarduino 0:e3fb1267e3c3 1636
cassyarduino 0:e3fb1267e3c3 1637 When the application is called, the global variable uip_len
cassyarduino 0:e3fb1267e3c3 1638 contains the length of the incoming data. The application can
cassyarduino 0:e3fb1267e3c3 1639 access the incoming data through the global pointer
cassyarduino 0:e3fb1267e3c3 1640 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
cassyarduino 0:e3fb1267e3c3 1641 bytes into the uip_buf array.
cassyarduino 0:e3fb1267e3c3 1642
cassyarduino 0:e3fb1267e3c3 1643 If the application wishes to send any data, this data should be
cassyarduino 0:e3fb1267e3c3 1644 put into the uip_appdata and the length of the data should be
cassyarduino 0:e3fb1267e3c3 1645 put into uip_len. If the application don't have any data to
cassyarduino 0:e3fb1267e3c3 1646 send, uip_len must be set to 0. */
cassyarduino 0:e3fb1267e3c3 1647 if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
cassyarduino 0:e3fb1267e3c3 1648 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1649 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1650
cassyarduino 0:e3fb1267e3c3 1651 appsend:
cassyarduino 0:e3fb1267e3c3 1652
cassyarduino 0:e3fb1267e3c3 1653 if(uip_flags & UIP_ABORT) {
cassyarduino 0:e3fb1267e3c3 1654 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1655 uip_connr->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 1656 BUF->flags = TCP_RST | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1657 goto tcp_send_nodata;
cassyarduino 0:e3fb1267e3c3 1658 }
cassyarduino 0:e3fb1267e3c3 1659
cassyarduino 0:e3fb1267e3c3 1660 if(uip_flags & UIP_CLOSE) {
cassyarduino 0:e3fb1267e3c3 1661 uip_slen = 0;
cassyarduino 0:e3fb1267e3c3 1662 uip_connr->len = 1;
cassyarduino 0:e3fb1267e3c3 1663 uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
cassyarduino 0:e3fb1267e3c3 1664 uip_connr->nrtx = 0;
cassyarduino 0:e3fb1267e3c3 1665 BUF->flags = TCP_FIN | TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1666 goto tcp_send_nodata;
cassyarduino 0:e3fb1267e3c3 1667 }
cassyarduino 0:e3fb1267e3c3 1668
cassyarduino 0:e3fb1267e3c3 1669 /* If uip_slen > 0, the application has data to be sent. */
cassyarduino 0:e3fb1267e3c3 1670 if(uip_slen > 0) {
cassyarduino 0:e3fb1267e3c3 1671
cassyarduino 0:e3fb1267e3c3 1672 /* If the connection has acknowledged data, the contents of
cassyarduino 0:e3fb1267e3c3 1673 the ->len variable should be discarded. */
cassyarduino 0:e3fb1267e3c3 1674 if((uip_flags & UIP_ACKDATA) != 0) {
cassyarduino 0:e3fb1267e3c3 1675 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1676 }
cassyarduino 0:e3fb1267e3c3 1677
cassyarduino 0:e3fb1267e3c3 1678 /* If the ->len variable is non-zero the connection has
cassyarduino 0:e3fb1267e3c3 1679 already data in transit and cannot send anymore right
cassyarduino 0:e3fb1267e3c3 1680 now. */
cassyarduino 0:e3fb1267e3c3 1681 if(uip_connr->len == 0) {
cassyarduino 0:e3fb1267e3c3 1682
cassyarduino 0:e3fb1267e3c3 1683 /* The application cannot send more than what is allowed by
cassyarduino 0:e3fb1267e3c3 1684 the mss (the minumum of the MSS and the available
cassyarduino 0:e3fb1267e3c3 1685 window). */
cassyarduino 0:e3fb1267e3c3 1686 if(uip_slen > uip_connr->mss) {
cassyarduino 0:e3fb1267e3c3 1687 uip_slen = uip_connr->mss;
cassyarduino 0:e3fb1267e3c3 1688 }
cassyarduino 0:e3fb1267e3c3 1689
cassyarduino 0:e3fb1267e3c3 1690 /* Remember how much data we send out now so that we know
cassyarduino 0:e3fb1267e3c3 1691 when everything has been acknowledged. */
cassyarduino 0:e3fb1267e3c3 1692 uip_connr->len = uip_slen;
cassyarduino 0:e3fb1267e3c3 1693 } else {
cassyarduino 0:e3fb1267e3c3 1694
cassyarduino 0:e3fb1267e3c3 1695 /* If the application already had unacknowledged data, we
cassyarduino 0:e3fb1267e3c3 1696 make sure that the application does not send (i.e.,
cassyarduino 0:e3fb1267e3c3 1697 retransmit) out more than it previously sent out. */
cassyarduino 0:e3fb1267e3c3 1698 uip_slen = uip_connr->len;
cassyarduino 0:e3fb1267e3c3 1699 }
cassyarduino 0:e3fb1267e3c3 1700 }
cassyarduino 0:e3fb1267e3c3 1701 uip_connr->nrtx = 0;
cassyarduino 0:e3fb1267e3c3 1702 apprexmit:
cassyarduino 0:e3fb1267e3c3 1703 uip_appdata = uip_sappdata;
cassyarduino 0:e3fb1267e3c3 1704
cassyarduino 0:e3fb1267e3c3 1705 /* If the application has data to be sent, or if the incoming
cassyarduino 0:e3fb1267e3c3 1706 packet had new data in it, we must send out a packet. */
cassyarduino 0:e3fb1267e3c3 1707 if(uip_slen > 0 && uip_connr->len > 0) {
cassyarduino 0:e3fb1267e3c3 1708 /* Add the length of the IP and TCP headers. */
cassyarduino 0:e3fb1267e3c3 1709 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
cassyarduino 0:e3fb1267e3c3 1710 /* We always set the ACK flag in response packets. */
cassyarduino 0:e3fb1267e3c3 1711 BUF->flags = TCP_ACK | TCP_PSH;
cassyarduino 0:e3fb1267e3c3 1712 /* Send the packet. */
cassyarduino 0:e3fb1267e3c3 1713 goto tcp_send_noopts;
cassyarduino 0:e3fb1267e3c3 1714 }
cassyarduino 0:e3fb1267e3c3 1715 /* If there is no data to send, just send out a pure ACK if
cassyarduino 0:e3fb1267e3c3 1716 there is newdata. */
cassyarduino 0:e3fb1267e3c3 1717 if(uip_flags & UIP_NEWDATA) {
cassyarduino 0:e3fb1267e3c3 1718 uip_len = UIP_TCPIP_HLEN;
cassyarduino 0:e3fb1267e3c3 1719 BUF->flags = TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1720 goto tcp_send_noopts;
cassyarduino 0:e3fb1267e3c3 1721 }
cassyarduino 0:e3fb1267e3c3 1722 }
cassyarduino 0:e3fb1267e3c3 1723 goto drop;
cassyarduino 0:e3fb1267e3c3 1724 case UIP_LAST_ACK:
cassyarduino 0:e3fb1267e3c3 1725 /* We can close this connection if the peer has acknowledged our
cassyarduino 0:e3fb1267e3c3 1726 FIN. This is indicated by the UIP_ACKDATA flag. */
cassyarduino 0:e3fb1267e3c3 1727 if(uip_flags & UIP_ACKDATA) {
cassyarduino 0:e3fb1267e3c3 1728 uip_connr->tcpstateflags = UIP_CLOSED;
cassyarduino 0:e3fb1267e3c3 1729 uip_flags = UIP_CLOSE;
cassyarduino 0:e3fb1267e3c3 1730 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1731 }
cassyarduino 0:e3fb1267e3c3 1732 break;
cassyarduino 0:e3fb1267e3c3 1733
cassyarduino 0:e3fb1267e3c3 1734 case UIP_FIN_WAIT_1:
cassyarduino 0:e3fb1267e3c3 1735 /* The application has closed the connection, but the remote host
cassyarduino 0:e3fb1267e3c3 1736 hasn't closed its end yet. Thus we do nothing but wait for a
cassyarduino 0:e3fb1267e3c3 1737 FIN from the other side. */
cassyarduino 0:e3fb1267e3c3 1738 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1739 uip_add_rcv_nxt(uip_len);
cassyarduino 0:e3fb1267e3c3 1740 }
cassyarduino 0:e3fb1267e3c3 1741 if(BUF->flags & TCP_FIN) {
cassyarduino 0:e3fb1267e3c3 1742 if(uip_flags & UIP_ACKDATA) {
cassyarduino 0:e3fb1267e3c3 1743 uip_connr->tcpstateflags = UIP_TIME_WAIT;
cassyarduino 0:e3fb1267e3c3 1744 uip_connr->timer = 0;
cassyarduino 0:e3fb1267e3c3 1745 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1746 } else {
cassyarduino 0:e3fb1267e3c3 1747 uip_connr->tcpstateflags = UIP_CLOSING;
cassyarduino 0:e3fb1267e3c3 1748 }
cassyarduino 0:e3fb1267e3c3 1749 uip_add_rcv_nxt(1);
cassyarduino 0:e3fb1267e3c3 1750 uip_flags = UIP_CLOSE;
cassyarduino 0:e3fb1267e3c3 1751 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1752 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1753 } else if(uip_flags & UIP_ACKDATA) {
cassyarduino 0:e3fb1267e3c3 1754 uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
cassyarduino 0:e3fb1267e3c3 1755 uip_connr->len = 0;
cassyarduino 0:e3fb1267e3c3 1756 goto drop;
cassyarduino 0:e3fb1267e3c3 1757 }
cassyarduino 0:e3fb1267e3c3 1758 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1759 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1760 }
cassyarduino 0:e3fb1267e3c3 1761 goto drop;
cassyarduino 0:e3fb1267e3c3 1762
cassyarduino 0:e3fb1267e3c3 1763 case UIP_FIN_WAIT_2:
cassyarduino 0:e3fb1267e3c3 1764 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1765 uip_add_rcv_nxt(uip_len);
cassyarduino 0:e3fb1267e3c3 1766 }
cassyarduino 0:e3fb1267e3c3 1767 if(BUF->flags & TCP_FIN) {
cassyarduino 0:e3fb1267e3c3 1768 uip_connr->tcpstateflags = UIP_TIME_WAIT;
cassyarduino 0:e3fb1267e3c3 1769 uip_connr->timer = 0;
cassyarduino 0:e3fb1267e3c3 1770 uip_add_rcv_nxt(1);
cassyarduino 0:e3fb1267e3c3 1771 uip_flags = UIP_CLOSE;
cassyarduino 0:e3fb1267e3c3 1772 UIP_APPCALL();
cassyarduino 0:e3fb1267e3c3 1773 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1774 }
cassyarduino 0:e3fb1267e3c3 1775 if(uip_len > 0) {
cassyarduino 0:e3fb1267e3c3 1776 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1777 }
cassyarduino 0:e3fb1267e3c3 1778 goto drop;
cassyarduino 0:e3fb1267e3c3 1779
cassyarduino 0:e3fb1267e3c3 1780 case UIP_TIME_WAIT:
cassyarduino 0:e3fb1267e3c3 1781 goto tcp_send_ack;
cassyarduino 0:e3fb1267e3c3 1782
cassyarduino 0:e3fb1267e3c3 1783 case UIP_CLOSING:
cassyarduino 0:e3fb1267e3c3 1784 if(uip_flags & UIP_ACKDATA) {
cassyarduino 0:e3fb1267e3c3 1785 uip_connr->tcpstateflags = UIP_TIME_WAIT;
cassyarduino 0:e3fb1267e3c3 1786 uip_connr->timer = 0;
cassyarduino 0:e3fb1267e3c3 1787 }
cassyarduino 0:e3fb1267e3c3 1788 }
cassyarduino 0:e3fb1267e3c3 1789 goto drop;
cassyarduino 0:e3fb1267e3c3 1790
cassyarduino 0:e3fb1267e3c3 1791
cassyarduino 0:e3fb1267e3c3 1792 /* We jump here when we are ready to send the packet, and just want
cassyarduino 0:e3fb1267e3c3 1793 to set the appropriate TCP sequence numbers in the TCP header. */
cassyarduino 0:e3fb1267e3c3 1794 tcp_send_ack:
cassyarduino 0:e3fb1267e3c3 1795 BUF->flags = TCP_ACK;
cassyarduino 0:e3fb1267e3c3 1796 tcp_send_nodata:
cassyarduino 0:e3fb1267e3c3 1797 uip_len = UIP_IPTCPH_LEN;
cassyarduino 0:e3fb1267e3c3 1798 tcp_send_noopts:
cassyarduino 0:e3fb1267e3c3 1799 BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
cassyarduino 0:e3fb1267e3c3 1800 tcp_send:
cassyarduino 0:e3fb1267e3c3 1801 /* We're done with the input processing. We are now ready to send a
cassyarduino 0:e3fb1267e3c3 1802 reply. Our job is to fill in all the fields of the TCP and IP
cassyarduino 0:e3fb1267e3c3 1803 headers before calculating the checksum and finally send the
cassyarduino 0:e3fb1267e3c3 1804 packet. */
cassyarduino 0:e3fb1267e3c3 1805 BUF->ackno[0] = uip_connr->rcv_nxt[0];
cassyarduino 0:e3fb1267e3c3 1806 BUF->ackno[1] = uip_connr->rcv_nxt[1];
cassyarduino 0:e3fb1267e3c3 1807 BUF->ackno[2] = uip_connr->rcv_nxt[2];
cassyarduino 0:e3fb1267e3c3 1808 BUF->ackno[3] = uip_connr->rcv_nxt[3];
cassyarduino 0:e3fb1267e3c3 1809
cassyarduino 0:e3fb1267e3c3 1810 BUF->seqno[0] = uip_connr->snd_nxt[0];
cassyarduino 0:e3fb1267e3c3 1811 BUF->seqno[1] = uip_connr->snd_nxt[1];
cassyarduino 0:e3fb1267e3c3 1812 BUF->seqno[2] = uip_connr->snd_nxt[2];
cassyarduino 0:e3fb1267e3c3 1813 BUF->seqno[3] = uip_connr->snd_nxt[3];
cassyarduino 0:e3fb1267e3c3 1814
cassyarduino 0:e3fb1267e3c3 1815 BUF->proto = UIP_PROTO_TCP;
cassyarduino 0:e3fb1267e3c3 1816
cassyarduino 0:e3fb1267e3c3 1817 BUF->srcport = uip_connr->lport;
cassyarduino 0:e3fb1267e3c3 1818 BUF->destport = uip_connr->rport;
cassyarduino 0:e3fb1267e3c3 1819
cassyarduino 0:e3fb1267e3c3 1820 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
cassyarduino 0:e3fb1267e3c3 1821 uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
cassyarduino 0:e3fb1267e3c3 1822
cassyarduino 0:e3fb1267e3c3 1823 if(uip_connr->tcpstateflags & UIP_STOPPED) {
cassyarduino 0:e3fb1267e3c3 1824 /* If the connection has issued uip_stop(), we advertise a zero
cassyarduino 0:e3fb1267e3c3 1825 window so that the remote host will stop sending data. */
cassyarduino 0:e3fb1267e3c3 1826 BUF->wnd[0] = BUF->wnd[1] = 0;
cassyarduino 0:e3fb1267e3c3 1827 } else {
cassyarduino 0:e3fb1267e3c3 1828 BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
cassyarduino 0:e3fb1267e3c3 1829 BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
cassyarduino 0:e3fb1267e3c3 1830 }
cassyarduino 0:e3fb1267e3c3 1831
cassyarduino 0:e3fb1267e3c3 1832 tcp_send_noconn:
cassyarduino 0:e3fb1267e3c3 1833 BUF->ttl = UIP_TTL;
cassyarduino 0:e3fb1267e3c3 1834 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 1835 /* For IPv6, the IP length field does not include the IPv6 IP header
cassyarduino 0:e3fb1267e3c3 1836 length. */
cassyarduino 0:e3fb1267e3c3 1837 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
cassyarduino 0:e3fb1267e3c3 1838 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
cassyarduino 0:e3fb1267e3c3 1839 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1840 BUF->len[0] = (uip_len >> 8);
cassyarduino 0:e3fb1267e3c3 1841 BUF->len[1] = (uip_len & 0xff);
cassyarduino 0:e3fb1267e3c3 1842 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1843
cassyarduino 0:e3fb1267e3c3 1844 BUF->urgp[0] = BUF->urgp[1] = 0;
cassyarduino 0:e3fb1267e3c3 1845
cassyarduino 0:e3fb1267e3c3 1846 /* Calculate TCP checksum. */
cassyarduino 0:e3fb1267e3c3 1847 BUF->tcpchksum = 0;
cassyarduino 0:e3fb1267e3c3 1848 BUF->tcpchksum = ~(uip_tcpchksum());
cassyarduino 0:e3fb1267e3c3 1849
cassyarduino 0:e3fb1267e3c3 1850 ip_send_nolen:
cassyarduino 0:e3fb1267e3c3 1851
cassyarduino 0:e3fb1267e3c3 1852 #if UIP_CONF_IPV6
cassyarduino 0:e3fb1267e3c3 1853 BUF->vtc = 0x60;
cassyarduino 0:e3fb1267e3c3 1854 BUF->tcflow = 0x00;
cassyarduino 0:e3fb1267e3c3 1855 BUF->flow = 0x00;
cassyarduino 0:e3fb1267e3c3 1856 #else /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1857 BUF->vhl = 0x45;
cassyarduino 0:e3fb1267e3c3 1858 BUF->tos = 0;
cassyarduino 0:e3fb1267e3c3 1859 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
cassyarduino 0:e3fb1267e3c3 1860 ++ipid;
cassyarduino 0:e3fb1267e3c3 1861 BUF->ipid[0] = ipid >> 8;
cassyarduino 0:e3fb1267e3c3 1862 BUF->ipid[1] = ipid & 0xff;
cassyarduino 0:e3fb1267e3c3 1863 /* Calculate IP checksum. */
cassyarduino 0:e3fb1267e3c3 1864 BUF->ipchksum = 0;
cassyarduino 0:e3fb1267e3c3 1865 BUF->ipchksum = ~(uip_ipchksum());
cassyarduino 0:e3fb1267e3c3 1866 DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
cassyarduino 0:e3fb1267e3c3 1867 #endif /* UIP_CONF_IPV6 */
cassyarduino 0:e3fb1267e3c3 1868
cassyarduino 0:e3fb1267e3c3 1869 UIP_STAT(++uip_stat.tcp.sent);
cassyarduino 0:e3fb1267e3c3 1870 send:
cassyarduino 0:e3fb1267e3c3 1871 DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
cassyarduino 0:e3fb1267e3c3 1872 (BUF->len[0] << 8) | BUF->len[1]);
cassyarduino 0:e3fb1267e3c3 1873
cassyarduino 0:e3fb1267e3c3 1874 UIP_STAT(++uip_stat.ip.sent);
cassyarduino 0:e3fb1267e3c3 1875 /* Return and let the caller do the actual transmission. */
cassyarduino 0:e3fb1267e3c3 1876 uip_flags = 0;
cassyarduino 0:e3fb1267e3c3 1877 return;
cassyarduino 0:e3fb1267e3c3 1878 drop:
cassyarduino 0:e3fb1267e3c3 1879 uip_len = 0;
cassyarduino 0:e3fb1267e3c3 1880 uip_flags = 0;
cassyarduino 0:e3fb1267e3c3 1881 return;
cassyarduino 0:e3fb1267e3c3 1882 }
cassyarduino 0:e3fb1267e3c3 1883 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 1884 u16_t
cassyarduino 0:e3fb1267e3c3 1885 htons(u16_t val)
cassyarduino 0:e3fb1267e3c3 1886 {
cassyarduino 0:e3fb1267e3c3 1887 return HTONS(val);
cassyarduino 0:e3fb1267e3c3 1888 }
cassyarduino 0:e3fb1267e3c3 1889 /*---------------------------------------------------------------------------*/
cassyarduino 0:e3fb1267e3c3 1890 void
cassyarduino 0:e3fb1267e3c3 1891 uip_send(const void *data, int len)
cassyarduino 0:e3fb1267e3c3 1892 {
cassyarduino 0:e3fb1267e3c3 1893 uip_slen = len;
cassyarduino 0:e3fb1267e3c3 1894 if(len > 0) {
cassyarduino 0:e3fb1267e3c3 1895 if(data != uip_sappdata) {
cassyarduino 0:e3fb1267e3c3 1896 memcpy(uip_sappdata, (data), uip_slen);
cassyarduino 0:e3fb1267e3c3 1897 }
cassyarduino 0:e3fb1267e3c3 1898 }
cassyarduino 0:e3fb1267e3c3 1899 }
cassyarduino 0:e3fb1267e3c3 1900 /** @} */