123

Committer:
hudakz
Date:
Sat Dec 20 11:10:40 2014 +0000
Revision:
3:5b17e4656dd0
Child:
4:d774541a34da
02 Name clash with "Ethernet" fixed for LPC1768

Who changed what in which revision?

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