Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Library for ENC28J60 Ethernet modules.

/media/uploads/hudakz/enc28j60_module01.jpg

Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!

  • Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
  • Works with both Mbed OS 2 and Mbed OS 5.

Usage:

  • Import the library into your project.
  • Add #include "UipEthernet.h" to main.cpp
  • Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.

Example programs:

Import programWebSwitch_ENC28J60

HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Import programHTTPServer_Echo_ENC28J60

A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.

Import programTcpServer_ENC28J60

Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programTcpClient_ENC28J60

Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpServer_ENC28J60

Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpClient_ENC28J60

Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programMQTT_Hello_ENC28J60

MQTT Client example program. Ethernet connection is via an ENC28J60 module.

Committer:
hudakz
Date:
Thu Jul 23 15:30:54 2020 +0000
Revision:
18:8d5738a6646e
Parent:
8:4acb22344932
Mbed library for ENC28J60 Ethernet modules.

Who changed what in which revision?

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