uIP 1.0 based webserver for LPC1114 + ENC28J60

Dependencies:   mbed TMP102

Committer:
ban4jp
Date:
Mon Jun 30 16:00:08 2014 +0000
Revision:
3:a2715e9c7737
Parent:
0:685224d2f66d
backported from Contiki 2.7

Who changed what in which revision?

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