Blame iscsiuio/src/uip/uip.c

Packit eace71
#include <netinet/in.h>
Packit eace71
#include <netinet/ip6.h>
Packit eace71
#include <netinet/icmp6.h>
Packit eace71
#include <sys/types.h>
Packit eace71
#include <arpa/inet.h>
Packit eace71
#include "uip.h"
Packit eace71
#include "dhcpc.h"
Packit eace71
#include "ipv6_ndpc.h"
Packit eace71
#include "brcm_iscsi.h"
Packit eace71
#include "ping.h"
Packit eace71
Packit eace71
/**
Packit eace71
 * \defgroup uip The uIP TCP/IP stack
Packit eace71
 * @{
Packit eace71
 *
Packit eace71
 * uIP is an implementation of the TCP/IP protocol stack intended for
Packit eace71
 * small 8-bit and 16-bit microcontrollers.
Packit eace71
 *
Packit eace71
 * uIP provides the necessary protocols for Internet communication,
Packit eace71
 * with a very small code footprint and RAM requirements - the uIP
Packit eace71
 * code size is on the order of a few kilobytes and RAM usage is on
Packit eace71
 * the order of a few hundred bytes.
Packit eace71
 */
Packit eace71
Packit eace71
/**
Packit eace71
 * \file
Packit eace71
 * The uIP TCP/IP stack code.
Packit eace71
 * \author Adam Dunkels <adam@dunkels.com>
Packit eace71
 */
Packit eace71
Packit eace71
/*
Packit eace71
 * Copyright (c) 2001-2003, Adam Dunkels.
Packit eace71
 * All rights reserved.
Packit eace71
 *
Packit eace71
 * Redistribution and use in source and binary forms, with or without
Packit eace71
 * modification, are permitted provided that the following conditions
Packit eace71
 * are met:
Packit eace71
 * 1. Redistributions of source code must retain the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer.
Packit eace71
 * 2. Redistributions in binary form must reproduce the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer in the
Packit eace71
 *    documentation and/or other materials provided with the distribution.
Packit eace71
 * 3. The name of the author may not be used to endorse or promote
Packit eace71
 *    products derived from this software without specific prior
Packit eace71
 *    written permission.
Packit eace71
 *
Packit eace71
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
Packit eace71
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit eace71
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit eace71
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
Packit eace71
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit eace71
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
Packit eace71
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit eace71
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit eace71
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit eace71
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit eace71
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit eace71
 *
Packit eace71
 * This file is part of the uIP TCP/IP stack.
Packit eace71
 *
Packit eace71
 *
Packit eace71
 */
Packit eace71
Packit eace71
/*
Packit eace71
 * uIP is a small implementation of the IP, UDP and TCP protocols (as
Packit eace71
 * well as some basic ICMP stuff). The implementation couples the IP,
Packit eace71
 * UDP, TCP and the application layers very tightly. To keep the size
Packit eace71
 * of the compiled code down, this code frequently uses the goto
Packit eace71
 * statement. While it would be possible to break the uip_process()
Packit eace71
 * function into many smaller functions, this would increase the code
Packit eace71
 * size because of the overhead of parameter passing and the fact that
Packit eace71
 * the optimier would not be as efficient.
Packit eace71
 *
Packit eace71
 * The principle is that we have a small buffer, called the uip_buf,
Packit eace71
 * in which the device driver puts an incoming packet. The TCP/IP
Packit eace71
 * stack parses the headers in the packet, and calls the
Packit eace71
 * application. If the remote host has sent data to the application,
Packit eace71
 * this data is present in the uip_buf and the application read the
Packit eace71
 * data from there. It is up to the application to put this data into
Packit eace71
 * a byte stream if needed. The application will not be fed with data
Packit eace71
 * that is out of sequence.
Packit eace71
 *
Packit eace71
 * If the application whishes to send data to the peer, it should put
Packit eace71
 * its data into the uip_buf. The uip_appdata pointer points to the
Packit eace71
 * first available byte. The TCP/IP stack will calculate the
Packit eace71
 * checksums, and fill in the necessary header fields and finally send
Packit eace71
 * the packet back to the peer.
Packit eace71
*/
Packit eace71
Packit eace71
#include "logger.h"
Packit eace71
Packit eace71
#include "uip.h"
Packit eace71
#include "uipopt.h"
Packit eace71
#include "uip_arch.h"
Packit eace71
#include "uip_eth.h"
Packit eace71
#include "uip-neighbor.h"
Packit eace71
Packit eace71
#include <string.h>
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 * Constants
Packit eace71
 ******************************************************************************/
Packit eace71
#define PFX "uip "
Packit eace71
Packit eace71
static const uip_ip4addr_t all_ones_addr4 = { 0xffff, 0xffff };
Packit eace71
Packit eace71
const uip_ip6addr_t all_zeroes_addr6 = {
Packit eace71
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
Packit eace71
};
Packit eace71
const uip_ip4addr_t all_zeroes_addr4 = { 0x0000, 0x0000 };
Packit eace71
Packit eace71
const uint8_t mutlicast_ipv6_prefix[16] = {
Packit eace71
	0xfc, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit eace71
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Packit eace71
};
Packit eace71
Packit eace71
const uint8_t link_local_addres_prefix[16] = {
Packit eace71
	0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit eace71
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Packit eace71
};
Packit eace71
const uint32_t link_local_address_prefix_length = 10;
Packit eace71
Packit eace71
/* Structures and definitions. */
Packit eace71
#define TCP_FIN 0x01
Packit eace71
#define TCP_SYN 0x02
Packit eace71
#define TCP_RST 0x04
Packit eace71
#define TCP_PSH 0x08
Packit eace71
#define TCP_ACK 0x10
Packit eace71
#define TCP_URG 0x20
Packit eace71
#define TCP_CTL 0x3f
Packit eace71
Packit eace71
#define TCP_OPT_END     0	/* End of TCP options list */
Packit eace71
#define TCP_OPT_NOOP    1	/* "No-operation" TCP option */
Packit eace71
#define TCP_OPT_MSS     2	/* Maximum segment size TCP option */
Packit eace71
Packit eace71
#define TCP_OPT_MSS_LEN 4	/* Length of TCP MSS option. */
Packit eace71
Packit eace71
#define ICMP_ECHO_REPLY 0
Packit eace71
#define ICMP_ECHO       8
Packit eace71
Packit eace71
#define ICMP6_ECHO_REPLY             129
Packit eace71
#define ICMP6_ECHO                   128
Packit eace71
#define ICMP6_NEIGHBOR_SOLICITATION  135
Packit eace71
#define ICMP6_NEIGHBOR_ADVERTISEMENT 136
Packit eace71
Packit eace71
#define ICMP6_FLAG_S (1 << 6)
Packit eace71
Packit eace71
#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
Packit eace71
#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
Packit eace71
Packit eace71
/* Macros. */
Packit eace71
#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
Packit eace71
#define UDPBUF(ustack) ((struct uip_udpip_hdr *)ustack->network_layer)
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * Utility Functions
Packit eace71
 *****************************************************************************/
Packit eace71
static int is_ipv6(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	u16_t type;
Packit eace71
Packit eace71
	type = ETH_BUF(ustack->uip_buf)->type;
Packit eace71
	type = ntohs(type);
Packit eace71
	if (type == UIP_ETHTYPE_8021Q)
Packit eace71
		type = ntohs(VLAN_ETH_BUF(ustack->uip_buf)->type);
Packit eace71
	else
Packit eace71
		type = ntohs(ETH_BUF(ustack->uip_buf)->type);
Packit eace71
Packit eace71
	return (type == UIP_ETHTYPE_IPv6);
Packit eace71
}
Packit eace71
Packit eace71
int is_ipv6_link_local_address(uip_ip6addr_t *addr)
Packit eace71
{
Packit eace71
	u8_t *test_adddr = (u8_t *) addr;
Packit eace71
	u8_t test_remainder;
Packit eace71
Packit eace71
	if (test_adddr[0] != link_local_addres_prefix[0])
Packit eace71
		return 0;
Packit eace71
Packit eace71
	test_remainder = (test_adddr[1] & 0xC0) >> 6;
Packit eace71
	if (test_remainder != 2)
Packit eace71
		return 0;
Packit eace71
Packit eace71
	return 1;
Packit eace71
}
Packit eace71
Packit eace71
void uip_sethostaddr4(struct uip_stack *ustack, uip_ip4addr_t *addr)
Packit eace71
{
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	uip_ip4addr_copy(ustack->hostaddr, (addr));
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
void uip_setdraddr4(struct uip_stack *ustack, uip_ip4addr_t *addr)
Packit eace71
{
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	uip_ip4addr_copy(ustack->default_route_addr, (addr));
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
void uip_setnetmask4(struct uip_stack *ustack, uip_ip4addr_t *addr)
Packit eace71
{
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	uip_ip4addr_copy(ustack->netmask, (addr));
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
void uip_setethernetmac(struct uip_stack *ustack, uint8_t *mac)
Packit eace71
{
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	memcpy(ustack->uip_ethaddr.addr, (mac), 6);
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
void set_uip_stack(struct uip_stack *ustack,
Packit eace71
		   uip_ip4addr_t *ip,
Packit eace71
		   uip_ip4addr_t *netmask,
Packit eace71
		   uip_ip4addr_t *default_route, uint8_t *mac_addr)
Packit eace71
{
Packit eace71
	if (ip)
Packit eace71
		uip_sethostaddr4(ustack, ip);
Packit eace71
	if (netmask)
Packit eace71
		uip_setnetmask4(ustack, netmask);
Packit eace71
	if (default_route)
Packit eace71
		uip_setdraddr4(ustack, default_route);
Packit eace71
	if (mac_addr)
Packit eace71
		uip_setethernetmac(ustack, mac_addr);
Packit eace71
}
Packit eace71
Packit eace71
#if !UIP_ARCH_ADD32
Packit eace71
void uip_add32(u8_t *op32, u16_t op16, u8_t *uip_acc32)
Packit eace71
{
Packit eace71
	uip_acc32[3] = op32[3] + (op16 & 0xff);
Packit eace71
	uip_acc32[2] = op32[2] + (op16 >> 8);
Packit eace71
	uip_acc32[1] = op32[1];
Packit eace71
	uip_acc32[0] = op32[0];
Packit eace71
Packit eace71
	if (uip_acc32[2] < (op16 >> 8)) {
Packit eace71
		++uip_acc32[1];
Packit eace71
		if (uip_acc32[1] == 0)
Packit eace71
			++uip_acc32[0];
Packit eace71
	}
Packit eace71
Packit eace71
	if (uip_acc32[3] < (op16 & 0xff)) {
Packit eace71
		++uip_acc32[2];
Packit eace71
		if (uip_acc32[2] == 0) {
Packit eace71
			++uip_acc32[1];
Packit eace71
			if (uip_acc32[1] == 0)
Packit eace71
				++uip_acc32[0];
Packit eace71
		}
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
#endif /* UIP_ARCH_ADD32 */
Packit eace71
Packit eace71
#if !UIP_ARCH_CHKSUM
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
static u16_t chksum(u16_t sum, const u8_t *data, u16_t len)
Packit eace71
{
Packit eace71
	u16_t t;
Packit eace71
	const u8_t *dataptr;
Packit eace71
	const u8_t *last_byte;
Packit eace71
Packit eace71
	dataptr = data;
Packit eace71
	last_byte = data + len - 1;
Packit eace71
Packit eace71
	while (dataptr < last_byte) {	/* At least two more bytes */
Packit eace71
		t = (dataptr[0] << 8) + dataptr[1];
Packit eace71
		sum += t;
Packit eace71
		if (sum < t)
Packit eace71
			sum++;	/* carry */
Packit eace71
		dataptr += 2;
Packit eace71
	}
Packit eace71
Packit eace71
	if (dataptr == last_byte) {
Packit eace71
		t = (dataptr[0] << 8) + 0;
Packit eace71
		sum += t;
Packit eace71
		if (sum < t)
Packit eace71
			sum++;	/* carry */
Packit eace71
	}
Packit eace71
Packit eace71
	/* Return sum in host byte order. */
Packit eace71
	return sum;
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
u16_t uip_chksum(u16_t *data, u16_t len)
Packit eace71
{
Packit eace71
	return htons(chksum(0, (u8_t *)data, len));
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
#ifndef UIP_ARCH_IPCHKSUM
Packit eace71
u16_t uip_ipchksum(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	u16_t sum;
Packit eace71
	u16_t uip_iph_len;
Packit eace71
Packit eace71
	if (is_ipv6(ustack))
Packit eace71
		uip_iph_len = UIP_IPv6_H_LEN;
Packit eace71
	else
Packit eace71
		uip_iph_len = UIP_IPv4_H_LEN;
Packit eace71
Packit eace71
	sum = chksum(0, ustack->network_layer, uip_iph_len);
Packit eace71
	return (sum == 0) ? 0xffff : htons(sum);
Packit eace71
}
Packit eace71
#endif
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
static u16_t upper_layer_chksum_ipv4(struct uip_stack *ustack, u8_t proto)
Packit eace71
{
Packit eace71
	u16_t upper_layer_len;
Packit eace71
	u16_t sum;
Packit eace71
	struct uip_tcp_ipv4_hdr *tcp_ipv4_hdr = NULL;
Packit eace71
Packit eace71
	tcp_ipv4_hdr = (struct uip_tcp_ipv4_hdr *)ustack->network_layer;
Packit eace71
Packit eace71
	upper_layer_len = (((u16_t) (tcp_ipv4_hdr->len[0]) << 8) +
Packit eace71
			   tcp_ipv4_hdr->len[1]) - UIP_IPv4_H_LEN;
Packit eace71
Packit eace71
	/* First sum pseudoheader. */
Packit eace71
	/* IP protocol and length fields. This addition cannot carry. */
Packit eace71
	sum = upper_layer_len + proto;
Packit eace71
Packit eace71
	sum =
Packit eace71
	    chksum(sum, (u8_t *)&tcp_ipv4_hdr->srcipaddr[0],
Packit eace71
		   2 * sizeof(uip_ip4addr_t));
Packit eace71
	/* Sum TCP header and data. */
Packit eace71
	sum = chksum(sum, ustack->network_layer + UIP_IPv4_H_LEN,
Packit eace71
		     upper_layer_len);
Packit eace71
Packit eace71
	return (sum == 0) ? 0xffff : htons(sum);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
static uint16_t upper_layer_checksum_ipv6(uint8_t *data, uint8_t proto)
Packit eace71
{
Packit eace71
	uint16_t upper_layer_len;
Packit eace71
	uint16_t sum;
Packit eace71
	struct ip6_hdr *ipv6_hdr;
Packit eace71
	uint8_t *upper_layer;
Packit eace71
	uint32_t val;
Packit eace71
Packit eace71
	ipv6_hdr = (struct ip6_hdr *)data;
Packit eace71
Packit eace71
	upper_layer_len = ntohs(ipv6_hdr->ip6_plen);
Packit eace71
Packit eace71
	/* First sum pseudoheader. */
Packit eace71
	sum = 0;
Packit eace71
	sum = chksum(sum, (const u8_t *)ipv6_hdr->ip6_src.s6_addr,
Packit eace71
		     sizeof(ipv6_hdr->ip6_src));
Packit eace71
	sum = chksum(sum, (const u8_t *)ipv6_hdr->ip6_dst.s6_addr,
Packit eace71
		     sizeof(ipv6_hdr->ip6_dst));
Packit eace71
Packit eace71
	val = htons(upper_layer_len);
Packit eace71
	sum = chksum(sum, (u8_t *)&val, sizeof(val));
Packit eace71
Packit eace71
	val = htons(proto);
Packit eace71
	sum = chksum(sum, (u8_t *)&val, sizeof(val));
Packit eace71
Packit eace71
	upper_layer = (uint8_t *)(ipv6_hdr + 1);
Packit eace71
	sum = chksum(sum, upper_layer, upper_layer_len);
Packit eace71
Packit eace71
	return (sum == 0) ? 0xffff : htons(sum);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
Packit eace71
u16_t uip_icmp6chksum(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	uint8_t *data = ustack->network_layer;
Packit eace71
Packit eace71
	return upper_layer_checksum_ipv6(data, UIP_PROTO_ICMP6);
Packit eace71
}
Packit eace71
Packit eace71
uint16_t icmpv6_checksum(uint8_t *data)
Packit eace71
{
Packit eace71
	return upper_layer_checksum_ipv6(data, IPPROTO_ICMPV6);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
u16_t uip_tcpchksum(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return upper_layer_chksum_ipv4(ustack, UIP_PROTO_TCP);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
#if UIP_UDP_CHECKSUMS
Packit eace71
static u16_t uip_udpchksum_ipv4(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return upper_layer_chksum_ipv4(ustack, UIP_PROTO_UDP);
Packit eace71
}
Packit eace71
Packit eace71
static u16_t uip_udpchksum_ipv6(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	uint8_t *data = ustack->network_layer;
Packit eace71
Packit eace71
	return upper_layer_checksum_ipv6(data, UIP_PROTO_UDP);
Packit eace71
}
Packit eace71
Packit eace71
u16_t uip_udpchksum(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	if (is_ipv6(ustack))
Packit eace71
		return uip_udpchksum_ipv6(ustack);
Packit eace71
	else
Packit eace71
		return uip_udpchksum_ipv4(ustack);
Packit eace71
}
Packit eace71
#endif /* UIP_UDP_CHECKSUMS */
Packit eace71
#endif /* UIP_ARCH_CHKSUM */
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_init(struct uip_stack *ustack, uint8_t ipv6_enabled)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
Packit eace71
	for (c = 0; c < UIP_LISTENPORTS; ++c)
Packit eace71
		ustack->uip_listenports[c] = 0;
Packit eace71
	for (c = 0; c < UIP_CONNS; ++c)
Packit eace71
		ustack->uip_conns[c].tcpstateflags = UIP_CLOSED;
Packit eace71
#if UIP_ACTIVE_OPEN
Packit eace71
	ustack->lastport = 1024;
Packit eace71
#endif /* UIP_ACTIVE_OPEN */
Packit eace71
Packit eace71
#if UIP_UDP
Packit eace71
	for (c = 0; c < UIP_UDP_CONNS; ++c)
Packit eace71
		ustack->uip_udp_conns[c].lport = 0;
Packit eace71
#endif /* UIP_UDP */
Packit eace71
Packit eace71
	/* IPv4 initialization. */
Packit eace71
#if UIP_FIXEDADDR == 0
Packit eace71
	/*  uip_hostaddr[0] = uip_hostaddr[1] = 0; */
Packit eace71
#endif /* UIP_FIXEDADDR */
Packit eace71
Packit eace71
	/*  zero out the uIP statistics */
Packit eace71
	memset(&ustack->stats, 0, sizeof(ustack->stats));
Packit eace71
Packit eace71
	/*  prepare the uIP lock */
Packit eace71
	pthread_mutex_init(&ustack->lock, NULL);
Packit eace71
Packit eace71
	if (ipv6_enabled)
Packit eace71
		ustack->enable_IPv6 = UIP_SUPPORT_IPv6_ENABLED;
Packit eace71
	else
Packit eace71
		ustack->enable_IPv6 = UIP_SUPPORT_IPv6_DISABLED;
Packit eace71
Packit eace71
	ustack->dhcpc = NULL;
Packit eace71
	ustack->ndpc = NULL;
Packit eace71
	ustack->ping_conf = NULL;
Packit eace71
}
Packit eace71
void uip_reset(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	/*  There was an associated DHCP object, this memory needs to be
Packit eace71
	 *  freed */
Packit eace71
	if (ustack->dhcpc)
Packit eace71
		free(ustack->dhcpc);
Packit eace71
Packit eace71
	ndpc_exit(ustack->ndpc);
Packit eace71
Packit eace71
	memset(ustack, 0, sizeof(*ustack));
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
#if UIP_ACTIVE_OPEN
Packit eace71
struct uip_conn *uip_connect(struct uip_stack *ustack, uip_ip4addr_t *ripaddr,
Packit eace71
			     u16_t rport)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
	register struct uip_conn *conn, *cconn;
Packit eace71
Packit eace71
	/* Find an unused local port. */
Packit eace71
again:
Packit eace71
	++ustack->lastport;
Packit eace71
Packit eace71
	if (ustack->lastport >= 32000)
Packit eace71
		ustack->lastport = 4096;
Packit eace71
Packit eace71
	/* Check if this port is already in use, and if so try to find
Packit eace71
	   another one. */
Packit eace71
	for (c = 0; c < UIP_CONNS; ++c) {
Packit eace71
		conn = &ustack->uip_conns[c];
Packit eace71
		if (conn->tcpstateflags != UIP_CLOSED &&
Packit eace71
		    conn->lport == htons(ustack->lastport)) {
Packit eace71
			goto again;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	conn = 0;
Packit eace71
	for (c = 0; c < UIP_CONNS; ++c) {
Packit eace71
		cconn = &ustack->uip_conns[c];
Packit eace71
		if (cconn->tcpstateflags == UIP_CLOSED) {
Packit eace71
			conn = cconn;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		if (cconn->tcpstateflags == UIP_TIME_WAIT) {
Packit eace71
			if (conn == 0 || cconn->timer > conn->timer)
Packit eace71
				conn = cconn;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (conn == 0)
Packit eace71
		return 0;
Packit eace71
Packit eace71
	conn->tcpstateflags = UIP_SYN_SENT;
Packit eace71
Packit eace71
	conn->snd_nxt[0] = ustack->iss[0];
Packit eace71
	conn->snd_nxt[1] = ustack->iss[1];
Packit eace71
	conn->snd_nxt[2] = ustack->iss[2];
Packit eace71
	conn->snd_nxt[3] = ustack->iss[3];
Packit eace71
Packit eace71
	conn->initialmss = conn->mss = UIP_TCP_MSS;
Packit eace71
Packit eace71
	conn->len = 1;		/* TCP length of the SYN is one. */
Packit eace71
	conn->nrtx = 0;
Packit eace71
	conn->timer = 1;	/* Send the SYN next time around. */
Packit eace71
	conn->rto = UIP_RTO;
Packit eace71
	conn->sa = 0;
Packit eace71
	conn->sv = 16;		/* Initial value of the RTT variance. */
Packit eace71
	conn->lport = htons(ustack->lastport);
Packit eace71
	conn->rport = rport;
Packit eace71
	uip_ip4addr_copy(&conn->ripaddr, ripaddr);
Packit eace71
Packit eace71
	return conn;
Packit eace71
}
Packit eace71
#endif /* UIP_ACTIVE_OPEN */
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
#if UIP_UDP
Packit eace71
struct uip_udp_conn *uip_udp_new(struct uip_stack *ustack,
Packit eace71
				 uip_ip4addr_t *ripaddr, u16_t rport)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
	register struct uip_udp_conn *conn;
Packit eace71
Packit eace71
	/* Find an unused local port. */
Packit eace71
again:
Packit eace71
	++ustack->lastport;
Packit eace71
Packit eace71
	if (ustack->lastport >= 32000)
Packit eace71
		ustack->lastport = 4096;
Packit eace71
Packit eace71
	for (c = 0; c < UIP_UDP_CONNS; ++c) {
Packit eace71
		if (ustack->uip_udp_conns[c].lport == htons(ustack->lastport))
Packit eace71
			goto again;
Packit eace71
	}
Packit eace71
Packit eace71
	conn = 0;
Packit eace71
	for (c = 0; c < UIP_UDP_CONNS; ++c) {
Packit eace71
		if (ustack->uip_udp_conns[c].lport == 0) {
Packit eace71
			conn = &ustack->uip_udp_conns[c];
Packit eace71
			break;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (conn == 0)
Packit eace71
		return 0;
Packit eace71
Packit eace71
	conn->lport = htons(ustack->lastport);
Packit eace71
	conn->rport = rport;
Packit eace71
	if (ripaddr == NULL)
Packit eace71
		memset(conn->ripaddr, 0, sizeof(uip_ip4addr_t));
Packit eace71
	else
Packit eace71
		uip_ip4addr_copy(&conn->ripaddr, ripaddr);
Packit eace71
	conn->ttl = UIP_TTL;
Packit eace71
Packit eace71
	return conn;
Packit eace71
}
Packit eace71
#endif /* UIP_UDP */
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_unlisten(struct uip_stack *ustack, u16_t port)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
Packit eace71
	for (c = 0; c < UIP_LISTENPORTS; ++c) {
Packit eace71
		if (ustack->uip_listenports[c] == port) {
Packit eace71
			ustack->uip_listenports[c] = 0;
Packit eace71
			return;
Packit eace71
		}
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_listen(struct uip_stack *ustack, u16_t port)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
Packit eace71
	for (c = 0; c < UIP_LISTENPORTS; ++c) {
Packit eace71
		if (ustack->uip_listenports[c] == 0) {
Packit eace71
			ustack->uip_listenports[c] = port;
Packit eace71
			return;
Packit eace71
		}
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Is new incoming data available?
Packit eace71
 *
Packit eace71
 * Will reduce to non-zero if there is new data for the application
Packit eace71
 * present at the uip_appdata pointer. The size of the data is
Packit eace71
 * avaliable through the uip_len variable.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_newdata(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_NEWDATA;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Has previously sent data been acknowledged?
Packit eace71
 *
Packit eace71
 * Will reduce to non-zero if the previously sent data has been
Packit eace71
 * acknowledged by the remote host. This means that the application
Packit eace71
 * can send new data.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
#define uip_acked()   (uip_flags & UIP_ACKDATA)
Packit eace71
Packit eace71
/**
Packit eace71
 * Has the connection just been connected?
Packit eace71
 *
Packit eace71
 * Reduces to non-zero if the current connection has been connected to
Packit eace71
 * a remote host. This will happen both if the connection has been
Packit eace71
 * actively opened (with uip_connect()) or passively opened (with
Packit eace71
 * uip_listen()).
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_connected(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_CONNECTED;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Has the connection been closed by the other end?
Packit eace71
 *
Packit eace71
 * Is non-zero if the connection has been closed by the remote
Packit eace71
 * host. The application may then do the necessary clean-ups.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_closed(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_CLOSE;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Has the connection been aborted by the other end?
Packit eace71
 *
Packit eace71
 * Non-zero if the current connection has been aborted (reset) by the
Packit eace71
 * remote host.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_aborted(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_ABORT;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Has the connection timed out?
Packit eace71
 *
Packit eace71
 * Non-zero if the current connection has been aborted due to too many
Packit eace71
 * retransmissions.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_timedout(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_TIMEDOUT;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Do we need to retransmit previously data?
Packit eace71
 *
Packit eace71
 * Reduces to non-zero if the previously sent data has been lost in
Packit eace71
 * the network, and the application should retransmit it. The
Packit eace71
 * application should send the exact same data as it did the last
Packit eace71
 * time, using the uip_send() function.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_rexmit(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_REXMIT;
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Is the connection being polled by uIP?
Packit eace71
 *
Packit eace71
 * Is non-zero if the reason the application is invoked is that the
Packit eace71
 * current connection has been idle for a while and should be
Packit eace71
 * polled.
Packit eace71
 *
Packit eace71
 * The polling event can be used for sending data without having to
Packit eace71
 * wait for the remote host to send data.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
int uip_poll(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_flags & UIP_POLL;
Packit eace71
}
Packit eace71
Packit eace71
int uip_initialmss(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_conn->initialmss;
Packit eace71
}
Packit eace71
Packit eace71
int uip_mss(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_conn->mss;
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
/* XXX: IP fragment reassembly: not well-tested. */
Packit eace71
Packit eace71
#if UIP_REASSEMBLY && !UIP_CONF_IPV6
Packit eace71
#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
Packit eace71
static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
Packit eace71
static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
Packit eace71
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
Packit eace71
	0x0f, 0x07, 0x03, 0x01
Packit eace71
};
Packit eace71
static u16_t uip_reasslen;
Packit eace71
static u8_t uip_reassflags;
Packit eace71
#define UIP_REASS_FLAG_LASTFRAG 0x01
Packit eace71
static u8_t uip_reasstmr;
Packit eace71
Packit eace71
#define IP_MF   0x20
Packit eace71
Packit eace71
static u8_t uip_reass(void)
Packit eace71
{
Packit eace71
	u16_t offset, len;
Packit eace71
	u16_t i;
Packit eace71
Packit eace71
	/* If ip_reasstmr is zero, no packet is present in the buffer, so we
Packit eace71
	   write the IP header of the fragment into the reassembly
Packit eace71
	   buffer. The timer is updated with the maximum age. */
Packit eace71
	if (uip_reasstmr == 0) {
Packit eace71
		memcpy(uip_reassbuf, &BUF(ustack)->vhl, uip_iph_len);
Packit eace71
		uip_reasstmr = UIP_REASS_MAXAGE;
Packit eace71
		uip_reassflags = 0;
Packit eace71
		/* Clear the bitmap. */
Packit eace71
		memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
Packit eace71
	}
Packit eace71
Packit eace71
	/* Check if the incoming fragment matches the one currently present
Packit eace71
	   in the reasembly buffer. If so, we proceed with copying the
Packit eace71
	   fragment into the buffer. */
Packit eace71
	if (BUF(ustack)->srcipaddr[0] == FBUF(ustack)->srcipaddr[0] &&
Packit eace71
	    BUF(ustack)->srcipaddr[1] == FBUF(ustack)->srcipaddr[1] &&
Packit eace71
	    BUF(ustack)->destipaddr[0] == FBUF(ustack)->destipaddr[0] &&
Packit eace71
	    BUF(ustack)->destipaddr[1] == FBUF(ustack)->destipaddr[1] &&
Packit eace71
	    BUF(ustack)->ipid[0] == FBUF(ustack)->ipid[0] &&
Packit eace71
	    BUF(ustack)->ipid[1] == FBUF(ustack)->ipid[1]) {
Packit eace71
Packit eace71
		len =
Packit eace71
		    (BUF(ustack)->len[0] << 8) + BUF(ustack)->len[1] -
Packit eace71
		    (BUF(ustack)->vhl & 0x0f) * 4;
Packit eace71
		offset =
Packit eace71
		    (((BUF(ustack)->ipoffset[0] & 0x3f) << 8) +
Packit eace71
		     BUF(ustack)->ipoffset[1]) * 8;
Packit eace71
Packit eace71
		/* If the offset or the offset + fragment length overflows the
Packit eace71
		   reassembly buffer, we discard the entire packet. */
Packit eace71
		if (offset > UIP_REASS_BUFSIZE ||
Packit eace71
		    offset + len > UIP_REASS_BUFSIZE) {
Packit eace71
			uip_reasstmr = 0;
Packit eace71
			goto nullreturn;
Packit eace71
		}
Packit eace71
Packit eace71
		/* Copy the fragment into the reassembly buffer, at the right
Packit eace71
		   offset. */
Packit eace71
		memcpy(&uip_reassbuf[uip_iph_len + offset],
Packit eace71
		       (char *)BUF + (int)((BUF(ustack)->vhl & 0x0f) * 4), len);
Packit eace71
Packit eace71
		/* Update the bitmap. */
Packit eace71
		if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
Packit eace71
			/* If the two endpoints are in the same byte, we only
Packit eace71
			   update that byte. */
Packit eace71
Packit eace71
			uip_reassbitmap[offset / (8 * 8)] |=
Packit eace71
			    bitmap_bits[(offset / 8) & 7] &
Packit eace71
			    ~bitmap_bits[((offset + len) / 8) & 7];
Packit eace71
		} else {
Packit eace71
			/* If the two endpoints are in different bytes, we
Packit eace71
			   update the bytes in the endpoints and fill the
Packit eace71
			   stuff inbetween with 0xff. */
Packit eace71
			uip_reassbitmap[offset / (8 * 8)] |=
Packit eace71
			    bitmap_bits[(offset / 8) & 7];
Packit eace71
			for (i = 1 + offset / (8 * 8);
Packit eace71
			     i < (offset + len) / (8 * 8); ++i) {
Packit eace71
				uip_reassbitmap[i] = 0xff;
Packit eace71
			}
Packit eace71
			uip_reassbitmap[(offset + len) / (8 * 8)] |=
Packit eace71
			    ~bitmap_bits[((offset + len) / 8) & 7];
Packit eace71
		}
Packit eace71
Packit eace71
		/* If this fragment has the More Fragments flag set to zero, we
Packit eace71
		   know that this is the last fragment, so we can calculate the
Packit eace71
		   size of the entire packet. We also set the
Packit eace71
		   IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
Packit eace71
		   the final fragment. */
Packit eace71
Packit eace71
		if ((BUF(ustack)->ipoffset[0] & IP_MF) == 0) {
Packit eace71
			uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
Packit eace71
			uip_reasslen = offset + len;
Packit eace71
		}
Packit eace71
Packit eace71
		/* Finally, we check if we have a full packet in the buffer.
Packit eace71
		   We do this by checking if we have the last fragment and if
Packit eace71
		   all bits in the bitmap are set. */
Packit eace71
		if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
Packit eace71
			/* Check all bytes up to and including all but the last
Packit eace71
			   byte in the bitmap. */
Packit eace71
			for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
Packit eace71
				if (uip_reassbitmap[i] != 0xff)
Packit eace71
					goto nullreturn;
Packit eace71
			}
Packit eace71
			/* Check the last byte in the bitmap. It should contain
Packit eace71
			   just the right amount of bits. */
Packit eace71
			if (uip_reassbitmap[uip_reasslen / (8 * 8)] !=
Packit eace71
			    (u8_t) ~bitmap_bits[uip_reasslen / 8 & 7])
Packit eace71
				goto nullreturn;
Packit eace71
Packit eace71
			/* If we have come this far, we have a full packet in
Packit eace71
			   the buffer, so we allocate a pbuf and copy the
Packit eace71
			   packet into it. We also reset the timer. */
Packit eace71
			uip_reasstmr = 0;
Packit eace71
			memcpy(BUF, FBUF, uip_reasslen);
Packit eace71
Packit eace71
			/* Pretend to be a "normal" (i.e., not fragmented) IP
Packit eace71
			   packet from now on. */
Packit eace71
			BUF(ustack)->ipoffset[0] = BUF(ustack)->ipoffset[1] = 0;
Packit eace71
			BUF(ustack)->len[0] = uip_reasslen >> 8;
Packit eace71
			BUF(ustack)->len[1] = uip_reasslen & 0xff;
Packit eace71
			BUF(ustack)->ipchksum = 0;
Packit eace71
			BUF(ustack)->ipchksum = ~(uip_ipchksum());
Packit eace71
Packit eace71
			return uip_reasslen;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
nullreturn:
Packit eace71
	return 0;
Packit eace71
}
Packit eace71
#endif /* UIP_REASSEMBLY */
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
static void uip_add_rcv_nxt(struct uip_stack *ustack, u16_t n)
Packit eace71
{
Packit eace71
	u8_t uip_acc32[4];
Packit eace71
Packit eace71
	uip_add32(ustack->uip_conn->rcv_nxt, n, uip_acc32);
Packit eace71
	ustack->uip_conn->rcv_nxt[0] = uip_acc32[0];
Packit eace71
	ustack->uip_conn->rcv_nxt[1] = uip_acc32[1];
Packit eace71
	ustack->uip_conn->rcv_nxt[2] = uip_acc32[2];
Packit eace71
	ustack->uip_conn->rcv_nxt[3] = uip_acc32[3];
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
Packit eace71
/** @} */
Packit eace71
Packit eace71
/**
Packit eace71
 * \defgroup uipdevfunc uIP device driver functions
Packit eace71
 * @{
Packit eace71
 *
Packit eace71
 * These functions are used by a network device driver for interacting
Packit eace71
 * with uIP.
Packit eace71
 */
Packit eace71
Packit eace71
/**
Packit eace71
 * Process an incoming packet.
Packit eace71
 *
Packit eace71
 * This function should be called when the device driver has received
Packit eace71
 * a packet from the network. The packet from the device driver must
Packit eace71
 * be present in the uip_buf buffer, and the length of the packet
Packit eace71
 * should be placed in the uip_len variable.
Packit eace71
 *
Packit eace71
 * When the function returns, there may be an outbound packet placed
Packit eace71
 * in the uip_buf packet buffer. If so, the uip_len variable is set to
Packit eace71
 * the length of the packet. If no packet is to be sent out, the
Packit eace71
 * uip_len variable is set to 0.
Packit eace71
 *
Packit eace71
 * The usual way of calling the function is presented by the source
Packit eace71
 * code below.
Packit eace71
 \code
Packit eace71
	uip_len = devicedriver_poll();
Packit eace71
	if(uip_len > 0) {
Packit eace71
		uip_input();
Packit eace71
		if(uip_len > 0) {
Packit eace71
			devicedriver_send();
Packit eace71
		}
Packit eace71
	}
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \note If you are writing a uIP device driver that needs ARP
Packit eace71
 * (Address Resolution Protocol), e.g., when running uIP over
Packit eace71
 * Ethernet, you will need to call the uIP ARP code before calling
Packit eace71
 * this function:
Packit eace71
 \code
Packit eace71
  #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
Packit eace71
  uip_len = ethernet_devicedrver_poll();
Packit eace71
  if(uip_len > 0) {
Packit eace71
	if (BUF(ustack)->type == HTONS(UIP_ETHTYPE_IP)) {
Packit eace71
		uip_arp_ipin();
Packit eace71
		uip_input();
Packit eace71
		if (uip_len > 0) {
Packit eace71
			uip_arp_out();
Packit eace71
			ethernet_devicedriver_send();
Packit eace71
		}
Packit eace71
	} else if (BUF(ustack)->type == HTONS(UIP_ETHTYPE_ARP)) {
Packit eace71
		uip_arp_arpin();
Packit eace71
		if (uip_len > 0)
Packit eace71
			ethernet_devicedriver_send();
Packit eace71
	}
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
void uip_input(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	uip_process(ustack, UIP_DATA);
Packit eace71
}
Packit eace71
Packit eace71
/**
Packit eace71
 * Periodic processing for a connection identified by its number.
Packit eace71
 *
Packit eace71
 * This function does the necessary periodic processing (timers,
Packit eace71
 * polling) for a uIP TCP conneciton, and should be called when the
Packit eace71
 * periodic uIP timer goes off. It should be called for every
Packit eace71
 * connection, regardless of whether they are open of closed.
Packit eace71
 *
Packit eace71
 * When the function returns, it may have an outbound packet waiting
Packit eace71
 * for service in the uIP packet buffer, and if so the uip_len
Packit eace71
 * variable is set to a value larger than zero. The device driver
Packit eace71
 * should be called to send out the packet.
Packit eace71
 *
Packit eace71
 * The ususal way of calling the function is through a for() loop like
Packit eace71
 * this:
Packit eace71
 \code
Packit eace71
	for(i = 0; i < UIP_CONNS; ++i) {
Packit eace71
		uip_periodic(i);
Packit eace71
		if(uip_len > 0) {
Packit eace71
			devicedriver_send();
Packit eace71
		}
Packit eace71
	}
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \note If you are writing a uIP device driver that needs ARP
Packit eace71
 * (Address Resolution Protocol), e.g., when running uIP over
Packit eace71
 * Ethernet, you will need to call the uip_arp_out() function before
Packit eace71
 * calling the device driver:
Packit eace71
 \code
Packit eace71
	for(i = 0; i < UIP_CONNS; ++i) {
Packit eace71
		uip_periodic(i);
Packit eace71
		if(uip_len > 0) {
Packit eace71
			uip_arp_out();
Packit eace71
			ethernet_devicedriver_send();
Packit eace71
		}
Packit eace71
	}
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \param conn The number of the connection which is to be periodically polled.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
void uip_periodic(struct uip_stack *ustack, int conn)
Packit eace71
{
Packit eace71
	ustack->uip_conn = &ustack->uip_conns[conn];
Packit eace71
	uip_process(ustack, UIP_TIMER);
Packit eace71
}
Packit eace71
Packit eace71
#if UIP_UDP
Packit eace71
/**
Packit eace71
 * Periodic processing for a UDP connection identified by its number.
Packit eace71
 *
Packit eace71
 * This function is essentially the same as uip_periodic(), but for
Packit eace71
 * UDP connections. It is called in a similar fashion as the
Packit eace71
 * uip_periodic() function:
Packit eace71
 \code
Packit eace71
  for(i = 0; i < UIP_UDP_CONNS; i++) {
Packit eace71
    uip_udp_periodic(i);
Packit eace71
    if(uip_len > 0) {
Packit eace71
      devicedriver_send();
Packit eace71
    }
Packit eace71
  }
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \note As for the uip_periodic() function, special care has to be
Packit eace71
 * taken when using uIP together with ARP and Ethernet:
Packit eace71
 \code
Packit eace71
  for(i = 0; i < UIP_UDP_CONNS; i++) {
Packit eace71
    uip_udp_periodic(i);
Packit eace71
    if(uip_len > 0) {
Packit eace71
      uip_arp_out();
Packit eace71
      ethernet_devicedriver_send();
Packit eace71
    }
Packit eace71
  }
Packit eace71
 \endcode
Packit eace71
 *
Packit eace71
 * \param conn The number of the UDP connection to be processed.
Packit eace71
 *
Packit eace71
 * \hideinitializer
Packit eace71
 */
Packit eace71
void uip_udp_periodic(struct uip_stack *ustack, int conn)
Packit eace71
{
Packit eace71
	ustack->uip_udp_conn = &ustack->uip_udp_conns[conn];
Packit eace71
	uip_process(ustack, UIP_UDP_TIMER);
Packit eace71
}
Packit eace71
#endif
Packit eace71
Packit eace71
void uip_ndp_periodic(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	uip_process(ustack, UIP_NDP_TIMER);
Packit eace71
}
Packit eace71
Packit eace71
void uip_process(struct uip_stack *ustack, u8_t flag)
Packit eace71
{
Packit eace71
	u8_t c;
Packit eace71
	u16_t tmp16;
Packit eace71
	register struct uip_conn *uip_connr = ustack->uip_conn;
Packit eace71
Packit eace71
	u16_t uip_iph_len = 0;
Packit eace71
	u16_t uip_ip_udph_len = 0;
Packit eace71
	u16_t uip_ip_tcph_len = 0;
Packit eace71
	struct ip6_hdr *ipv6_hdr = NULL;
Packit eace71
	struct uip_tcp_ipv4_hdr *tcp_ipv4_hdr = NULL;
Packit eace71
	struct uip_tcp_hdr *tcp_hdr = NULL;
Packit eace71
	struct uip_icmpv4_hdr *icmpv4_hdr = NULL;
Packit eace71
	struct uip_icmpv6_hdr *icmpv6_hdr __attribute__((__unused__)) = NULL;
Packit eace71
	struct uip_udp_hdr *udp_hdr = NULL;
Packit eace71
Packit eace71
	/*  Drop invalid packets */
Packit eace71
	if (ustack->uip_buf == NULL) {
Packit eace71
		LOG_ERR(PFX "ustack->uip_buf == NULL.");
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		uint8_t *buf;
Packit eace71
		uip_iph_len = UIP_IPv6_H_LEN;
Packit eace71
		uip_ip_udph_len = UIP_IPv6_UDPH_LEN;
Packit eace71
		uip_ip_tcph_len = UIP_IPv6_TCPH_LEN;
Packit eace71
Packit eace71
		ipv6_hdr = (struct ip6_hdr *)ustack->network_layer;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv6_hdr);
Packit eace71
		tcp_hdr = (struct uip_tcp_hdr *)buf;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv6_hdr);
Packit eace71
		udp_hdr = (struct uip_udp_hdr *)buf;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv6_hdr);
Packit eace71
		icmpv6_hdr = (struct uip_icmpv6_hdr *)buf;
Packit eace71
	} else {
Packit eace71
		uint8_t *buf;
Packit eace71
Packit eace71
		uip_iph_len = UIP_IPv4_H_LEN;
Packit eace71
		uip_ip_udph_len = UIP_IPv4_UDPH_LEN;
Packit eace71
		uip_ip_tcph_len = UIP_IPv4_TCPH_LEN;
Packit eace71
Packit eace71
		tcp_ipv4_hdr = (struct uip_tcp_ipv4_hdr *)ustack->network_layer;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv4_hdr);
Packit eace71
		tcp_hdr = (struct uip_tcp_hdr *)buf;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv4_hdr);
Packit eace71
		icmpv4_hdr = (struct uip_icmpv4_hdr *)buf;
Packit eace71
Packit eace71
		buf = ustack->network_layer;
Packit eace71
		buf += sizeof(struct uip_ipv4_hdr);
Packit eace71
		udp_hdr = (struct uip_udp_hdr *)buf;
Packit eace71
	}			/* End of ipv6 */
Packit eace71
Packit eace71
#if UIP_UDP
Packit eace71
	if (flag == UIP_UDP_SEND_CONN)
Packit eace71
		goto udp_send;
Packit eace71
#endif /* UIP_UDP */
Packit eace71
	ustack->uip_sappdata = ustack->uip_appdata = ustack->network_layer +
Packit eace71
	    uip_ip_tcph_len;
Packit eace71
Packit eace71
	/* Check if we were invoked because of a poll request for a
Packit eace71
	   particular connection. */
Packit eace71
	if (flag == UIP_POLL_REQUEST) {
Packit eace71
		if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED
Packit eace71
		    && !uip_outstanding(uip_connr)) {
Packit eace71
			ustack->uip_flags = UIP_POLL;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			goto appsend;
Packit eace71
		}
Packit eace71
		goto drop;
Packit eace71
Packit eace71
		/* Check if we were invoked because of the perodic timer
Packit eace71
		   firing. */
Packit eace71
	} else if (flag == UIP_TIMER) {
Packit eace71
#if UIP_REASSEMBLY
Packit eace71
		if (uip_reasstmr != 0)
Packit eace71
			--uip_reasstmr;
Packit eace71
#endif /* UIP_REASSEMBLY */
Packit eace71
		/* Increase the initial sequence number. */
Packit eace71
		if (++ustack->iss[3] == 0) {
Packit eace71
			if (++ustack->iss[2] == 0) {
Packit eace71
				if (++ustack->iss[1] == 0)
Packit eace71
					++ustack->iss[0];
Packit eace71
			}
Packit eace71
		}
Packit eace71
Packit eace71
		/* Reset the length variables. */
Packit eace71
		ustack->uip_len = 0;
Packit eace71
		ustack->uip_slen = 0;
Packit eace71
Packit eace71
		/* Check if the connection is in a state in which we simply wait
Packit eace71
		   for the connection to time out. If so, we increase the
Packit eace71
		   connection's timer and remove the connection if it times
Packit eace71
		   out. */
Packit eace71
		if (uip_connr->tcpstateflags == UIP_TIME_WAIT ||
Packit eace71
		    uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
Packit eace71
			++(uip_connr->timer);
Packit eace71
			if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT)
Packit eace71
				uip_connr->tcpstateflags = UIP_CLOSED;
Packit eace71
		} else if (uip_connr->tcpstateflags != UIP_CLOSED) {
Packit eace71
			/* If the connection has outstanding data, we increase
Packit eace71
			   the connection's timer and see if it has reached the
Packit eace71
			   RTO value in which case we retransmit. */
Packit eace71
			if (uip_outstanding(uip_connr)) {
Packit eace71
				if (uip_connr->timer-- == 0) {
Packit eace71
					if (uip_connr->nrtx == UIP_MAXRTX ||
Packit eace71
					    ((uip_connr->tcpstateflags ==
Packit eace71
					      UIP_SYN_SENT
Packit eace71
					      || uip_connr->tcpstateflags ==
Packit eace71
					      UIP_SYN_RCVD)
Packit eace71
					     && uip_connr->nrtx ==
Packit eace71
					     UIP_MAXSYNRTX)) {
Packit eace71
						uip_connr->tcpstateflags =
Packit eace71
						    UIP_CLOSED;
Packit eace71
Packit eace71
						/* We call UIP_APPCALL() with
Packit eace71
						   uip_flags set to UIP_TIMEDOUT
Packit eace71
						   to inform the application
Packit eace71
						   that the connection has timed
Packit eace71
						   out. */
Packit eace71
						ustack->uip_flags =
Packit eace71
						    UIP_TIMEDOUT;
Packit eace71
						UIP_APPCALL(ustack);
Packit eace71
Packit eace71
						/* We also send a reset packet
Packit eace71
						   to the remote host. */
Packit eace71
						tcp_hdr->flags =
Packit eace71
						    TCP_RST | TCP_ACK;
Packit eace71
						goto tcp_send_nodata;
Packit eace71
					}
Packit eace71
Packit eace71
					/* Exponential backoff. */
Packit eace71
					uip_connr->timer =
Packit eace71
					    UIP_RTO << (uip_connr->nrtx >
Packit eace71
							4 ? 4 : uip_connr->
Packit eace71
							nrtx);
Packit eace71
					++(uip_connr->nrtx);
Packit eace71
Packit eace71
					/* Ok, so we need to retransmit.
Packit eace71
					   We do this differently depending on
Packit eace71
					   which state we are in.
Packit eace71
					   In ESTABLISHED, we call upon the
Packit eace71
					   application so that it may prepare
Packit eace71
					   the data for the retransmit.
Packit eace71
					   In SYN_RCVD, we resend the SYNACK
Packit eace71
					   that we sent earlier and in LAST_ACK
Packit eace71
					   we have to retransmit our FINACK. */
Packit eace71
					++ustack->stats.tcp.rexmit;
Packit eace71
					switch (uip_connr->
Packit eace71
						tcpstateflags & UIP_TS_MASK) {
Packit eace71
					case UIP_SYN_RCVD:
Packit eace71
						/* In the SYN_RCVD state, we
Packit eace71
						   should retransmit our SYNACK
Packit eace71
						 */
Packit eace71
						goto tcp_send_synack;
Packit eace71
#if UIP_ACTIVE_OPEN
Packit eace71
					case UIP_SYN_SENT:
Packit eace71
						/* In the SYN_SENT state,
Packit eace71
						   we retransmit out SYN. */
Packit eace71
						tcp_hdr->flags = 0;
Packit eace71
						goto tcp_send_syn;
Packit eace71
#endif /* UIP_ACTIVE_OPEN */
Packit eace71
Packit eace71
					case UIP_ESTABLISHED:
Packit eace71
						/* In the ESTABLISHED state,
Packit eace71
						   we call upon the application
Packit eace71
						   to do the actual retransmit
Packit eace71
						   after which we jump into
Packit eace71
						   the code for sending out the
Packit eace71
						   packet (the apprexmit
Packit eace71
						   label). */
Packit eace71
						ustack->uip_flags = UIP_REXMIT;
Packit eace71
						UIP_APPCALL(ustack);
Packit eace71
						goto apprexmit;
Packit eace71
Packit eace71
					case UIP_FIN_WAIT_1:
Packit eace71
					case UIP_CLOSING:
Packit eace71
					case UIP_LAST_ACK:
Packit eace71
						/* In all these states we should
Packit eace71
						   retransmit a FINACK. */
Packit eace71
						goto tcp_send_finack;
Packit eace71
Packit eace71
					}
Packit eace71
				}
Packit eace71
			} else if ((uip_connr->tcpstateflags & UIP_TS_MASK) ==
Packit eace71
				   UIP_ESTABLISHED) {
Packit eace71
				/* If there was no need for a retransmission,
Packit eace71
				   we poll the application for new data. */
Packit eace71
				ustack->uip_flags = UIP_POLL;
Packit eace71
				UIP_APPCALL(ustack);
Packit eace71
				goto appsend;
Packit eace71
			}
Packit eace71
		}
Packit eace71
		goto drop;
Packit eace71
	}			/* End of UIP_TIMER */
Packit eace71
#if UIP_UDP
Packit eace71
	if (flag == UIP_UDP_TIMER) {
Packit eace71
		/* This is for IPv4 DHCP only! */
Packit eace71
		if (ustack->uip_udp_conn->lport != 0) {
Packit eace71
			ustack->uip_conn = NULL;
Packit eace71
			ustack->uip_sappdata = ustack->uip_appdata =
Packit eace71
			    ustack->network_layer + uip_ip_udph_len;
Packit eace71
			ustack->uip_len = ustack->uip_slen = 0;
Packit eace71
			ustack->uip_flags = UIP_POLL;
Packit eace71
			UIP_UDP_APPCALL(ustack);
Packit eace71
			goto udp_send;
Packit eace71
		} else {
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	}
Packit eace71
#endif
Packit eace71
	if (flag == UIP_NDP_TIMER) {
Packit eace71
		/* This is for IPv6 NDP Only! */
Packit eace71
		if (1) {	/* If NDP engine active */
Packit eace71
			ustack->uip_len = ustack->uip_slen = 0;
Packit eace71
			ustack->uip_flags = UIP_POLL;
Packit eace71
			goto ndp_send;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* This is where the input processing starts. */
Packit eace71
	++ustack->stats.ip.recv;
Packit eace71
Packit eace71
	/* Start of IP input header processing code. */
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		u8_t version = ((ipv6_hdr->ip6_vfc) & 0xf0) >> 4;
Packit eace71
Packit eace71
		/* Check validity of the IP header. */
Packit eace71
		if (version != 0x6) {	/* IP version and header length. */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.vhlerr;
Packit eace71
			LOG_DEBUG(PFX "ipv6: invalid version(0x%x).", version);
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	} else {
Packit eace71
		/* Check validity of the IP header. */
Packit eace71
		if (tcp_ipv4_hdr->vhl != 0x45) {
Packit eace71
			/* IP version and header length. */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.vhlerr;
Packit eace71
			LOG_DEBUG(PFX
Packit eace71
				  "ipv4: invalid version or header length: "
Packit eace71
				  "0x%x.",
Packit eace71
				  tcp_ipv4_hdr->vhl);
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* Check the size of the packet. If the size reported to us in
Packit eace71
	   uip_len is smaller the size reported in the IP header, we assume
Packit eace71
	   that the packet has been corrupted in transit. If the size of
Packit eace71
	   uip_len is larger than the size reported in the IP packet header,
Packit eace71
	   the packet has been padded and we set uip_len to the correct
Packit eace71
	   value.. */
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		u16_t len = ntohs(ipv6_hdr->ip6_plen);
Packit eace71
		if (len > ustack->uip_len) {
Packit eace71
			LOG_DEBUG(PFX
Packit eace71
				 "ip: packet shorter than reported in IP header"
Packit eace71
				 ":IPv6_BUF(ustack)->len: %d ustack->uip_len: "
Packit eace71
				 "%d", len, ustack->uip_len);
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	} else {
Packit eace71
		if ((tcp_ipv4_hdr->len[0] << 8) +
Packit eace71
		    tcp_ipv4_hdr->len[1] <= ustack->uip_len) {
Packit eace71
			ustack->uip_len = (tcp_ipv4_hdr->len[0] << 8) +
Packit eace71
			    tcp_ipv4_hdr->len[1];
Packit eace71
		} else {
Packit eace71
			LOG_DEBUG(PFX
Packit eace71
				 "ip: packet shorter than reported in IP header"
Packit eace71
				 ":tcp_ipv4_hdr->len: %d ustack->uip_len:%d.",
Packit eace71
				 (tcp_ipv4_hdr->len[0] << 8) +
Packit eace71
				 tcp_ipv4_hdr->len[1], ustack->uip_len);
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (!is_ipv6(ustack)) {
Packit eace71
		/* Check the fragment flag. */
Packit eace71
		if ((tcp_ipv4_hdr->ipoffset[0] & 0x3f) != 0 ||
Packit eace71
		    tcp_ipv4_hdr->ipoffset[1] != 0) {
Packit eace71
#if UIP_REASSEMBLY
Packit eace71
			uip_len = uip_reass();
Packit eace71
			if (uip_len == 0)
Packit eace71
				goto drop;
Packit eace71
#else /* UIP_REASSEMBLY */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.fragerr;
Packit eace71
			LOG_WARN(PFX "ip: fragment dropped.");
Packit eace71
			goto drop;
Packit eace71
#endif /* UIP_REASSEMBLY */
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (!is_ipv6(ustack)) {
Packit eace71
		/* ipv4 */
Packit eace71
		if (uip_ip4addr_cmp(ustack->hostaddr, all_zeroes_addr4)) {
Packit eace71
			/* If we are configured to use ping IP address
Packit eace71
			   configuration and hasn't been assigned an IP
Packit eace71
			   address yet, we accept all ICMP packets. */
Packit eace71
#if UIP_PINGADDRCONF && !UIP_CONF_IPV6
Packit eace71
			if (tcp_ipv4_hdr->proto == UIP_PROTO_ICMP) {
Packit eace71
				LOG_WARN(PFX
Packit eace71
					 "ip: possible ping config packet "
Packit eace71
					 "received.");
Packit eace71
				goto icmp_input;
Packit eace71
			} else {
Packit eace71
				LOG_WARN(PFX
Packit eace71
					 "ip: packet dropped since no "
Packit eace71
					 "address assigned.");
Packit eace71
				goto drop;
Packit eace71
			}
Packit eace71
#endif /* UIP_PINGADDRCONF */
Packit eace71
		} else {
Packit eace71
			int broadcast_addr = 0xFFFFFFFF;
Packit eace71
			/* If IP broadcast support is configured, we check for
Packit eace71
			   a broadcast UDP packet, which may be destined to us
Packit eace71
			 */
Packit eace71
			if ((tcp_ipv4_hdr->proto == UIP_PROTO_UDP) &&
Packit eace71
			    (uip_ip4addr_cmp
Packit eace71
			     (tcp_ipv4_hdr->destipaddr, &broadcast_addr))
Packit eace71
			    /*&&
Packit eace71
			       uip_ipchksum() == 0xffff */
Packit eace71
			    ) {
Packit eace71
				goto udp_input;
Packit eace71
			}
Packit eace71
Packit eace71
			/* Check if the packet is destined for our IP address
Packit eace71
			 */
Packit eace71
			if (!uip_ip4addr_cmp(tcp_ipv4_hdr->destipaddr,
Packit eace71
					     ustack->hostaddr)) {
Packit eace71
				++ustack->stats.ip.drop;
Packit eace71
				goto drop;
Packit eace71
			}
Packit eace71
		}
Packit eace71
		if (uip_ipchksum(ustack) != 0xffff) {
Packit eace71
			/* Compute and check the IP header checksum. */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.chkerr;
Packit eace71
			LOG_ERR(PFX "ip: bad checksum.");
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	}  /* End of ipv4 */
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		if (ipv6_hdr->ip6_nxt == UIP_PROTO_TCP) {
Packit eace71
			/* Check for TCP packet. If so, proceed with TCP input
Packit eace71
			   processing. */
Packit eace71
			goto ndp_newdata;
Packit eace71
		}
Packit eace71
#if UIP_UDP
Packit eace71
		if (ipv6_hdr->ip6_nxt == UIP_PROTO_UDP)
Packit eace71
			goto ndp_newdata;
Packit eace71
#endif /* UIP_UDP */
Packit eace71
Packit eace71
		/* This is IPv6 ICMPv6 processing code. */
Packit eace71
		if (ipv6_hdr->ip6_nxt != UIP_PROTO_ICMP6) {
Packit eace71
			/* We only allow ICMPv6 packets from here. */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.protoerr;
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
Packit eace71
		++ustack->stats.icmp.recv;
Packit eace71
Packit eace71
ndp_newdata:
Packit eace71
		/* This call is to handle the IPv6 Network Discovery Protocol */
Packit eace71
		ustack->uip_flags = UIP_NEWDATA;
Packit eace71
		ustack->uip_slen = 0;
Packit eace71
ndp_send:
Packit eace71
		UIP_NDP_CALL(ustack);
Packit eace71
		if (ustack->uip_slen != 0) {
Packit eace71
			ustack->uip_len = ustack->uip_slen;
Packit eace71
			goto send;
Packit eace71
		} else {
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
	} else {
Packit eace71
		/* IPv4 Processing */
Packit eace71
		if (tcp_ipv4_hdr->proto == UIP_PROTO_TCP) {
Packit eace71
			/* Check for TCP packet. If so, proceed with TCP input
Packit eace71
			   processing. */
Packit eace71
			goto tcp_input;
Packit eace71
		}
Packit eace71
#if UIP_UDP
Packit eace71
		if (tcp_ipv4_hdr->proto == UIP_PROTO_UDP)
Packit eace71
			goto udp_input;
Packit eace71
#endif /* UIP_UDP */
Packit eace71
Packit eace71
		/* ICMPv4 processing code follows. */
Packit eace71
		if (tcp_ipv4_hdr->proto != UIP_PROTO_ICMP) {
Packit eace71
			/* We only allow ICMP packets from here. */
Packit eace71
			++ustack->stats.ip.drop;
Packit eace71
			++ustack->stats.ip.protoerr;
Packit eace71
			LOG_DEBUG(PFX "ip: neither tcp nor icmp.");
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
#if UIP_PINGADDRCONF
Packit eace71
icmp_input:
Packit eace71
#endif /* UIP_PINGADDRCONF */
Packit eace71
		++ustack->stats.icmp.recv;
Packit eace71
Packit eace71
		if (icmpv4_hdr->type == ICMP_ECHO_REPLY) {
Packit eace71
			if (process_icmp_packet(icmpv4_hdr, ustack) == 0)
Packit eace71
				goto drop;
Packit eace71
		}
Packit eace71
Packit eace71
		/* ICMP echo (i.e., ping) processing. This is simple, we only
Packit eace71
		   change the ICMP type from ECHO to ECHO_REPLY and adjust the
Packit eace71
		   ICMP checksum before we return the packet. */
Packit eace71
		if (icmpv4_hdr->type != ICMP_ECHO) {
Packit eace71
			++ustack->stats.icmp.drop;
Packit eace71
			++ustack->stats.icmp.typeerr;
Packit eace71
			LOG_DEBUG(PFX "icmp: not icmp echo.");
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
Packit eace71
		/* If we are configured to use ping IP address assignment, we
Packit eace71
		   use the destination IP address of this ping packet and assign
Packit eace71
		   it to ourself. */
Packit eace71
#if UIP_PINGADDRCONF
Packit eace71
		if ((ustack->hostaddr[0] | ustack->hostaddr[1]) == 0) {
Packit eace71
			ustack->hostaddr[0] = tcp_ipv4_hdr->destipaddr[0];
Packit eace71
			ustack->hostaddr[1] = tcp_ipv4_hdr->destipaddr[1];
Packit eace71
		}
Packit eace71
#endif /* UIP_PINGADDRCONF */
Packit eace71
Packit eace71
		icmpv4_hdr->type = ICMP_ECHO_REPLY;
Packit eace71
Packit eace71
		if (icmpv4_hdr->icmpchksum >= htons(0xffff -
Packit eace71
						    (ICMP_ECHO << 8))) {
Packit eace71
			icmpv4_hdr->icmpchksum += htons(ICMP_ECHO << 8) + 1;
Packit eace71
		} else {
Packit eace71
			icmpv4_hdr->icmpchksum += htons(ICMP_ECHO << 8);
Packit eace71
		}
Packit eace71
Packit eace71
		/* Swap IP addresses. */
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
Packit eace71
				 tcp_ipv4_hdr->srcipaddr);
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
Packit eace71
Packit eace71
		++ustack->stats.icmp.sent;
Packit eace71
		goto send;
Packit eace71
Packit eace71
		/* End of IPv4 input header processing code. */
Packit eace71
	}
Packit eace71
Packit eace71
#if UIP_UDP
Packit eace71
	/* UDP input processing. */
Packit eace71
udp_input:
Packit eace71
	/* UDP processing is really just a hack. We don't do anything to the
Packit eace71
	   UDP/IP headers, but let the UDP application do all the hard
Packit eace71
	   work. If the application sets uip_slen, it has a packet to
Packit eace71
	   send. */
Packit eace71
#if UIP_UDP_CHECKSUMS
Packit eace71
	ustack->uip_len = ustack->uip_len - uip_ip_udph_len;
Packit eace71
	ustack->uip_appdata = ustack->network_layer + uip_ip_udph_len;
Packit eace71
	if (UDPBUF(ustack)->udpchksum != 0 && uip_udpchksum(ustack) != 0xffff) {
Packit eace71
		++ustack->stats.udp.drop;
Packit eace71
		++ustack->stats.udp.chkerr;
Packit eace71
		LOG_DEBUG(PFX "udp: bad checksum.");
Packit eace71
		goto drop;
Packit eace71
	}
Packit eace71
#else /* UIP_UDP_CHECKSUMS */
Packit eace71
	uip_len = uip_len - uip_ip_udph_len;
Packit eace71
#endif /* UIP_UDP_CHECKSUMS */
Packit eace71
Packit eace71
	if (is_ipv6(ustack))
Packit eace71
		goto udp_found;
Packit eace71
Packit eace71
	/* Demultiplex this UDP packet between the UDP "connections". */
Packit eace71
	for (ustack->uip_udp_conn = &ustack->uip_udp_conns[0];
Packit eace71
	     ustack->uip_udp_conn < &ustack->uip_udp_conns[UIP_UDP_CONNS];
Packit eace71
	     ++ustack->uip_udp_conn) {
Packit eace71
		/* If the local UDP port is non-zero, the connection is
Packit eace71
		   considered to be used. If so, the local port number is
Packit eace71
		   checked against the destination port number in the
Packit eace71
		   received packet. If the two port
Packit eace71
		   numbers match, the remote port number is checked if the
Packit eace71
		   connection is bound to a remote port. Finally, if the
Packit eace71
		   connection is bound to a remote IP address, the source IP
Packit eace71
		   address of the packet is checked. */
Packit eace71
Packit eace71
		if (ustack->uip_udp_conn->lport != 0 &&
Packit eace71
		    UDPBUF(ustack)->destport == ustack->uip_udp_conn->lport &&
Packit eace71
		    (ustack->uip_udp_conn->rport == 0 ||
Packit eace71
		     UDPBUF(ustack)->srcport == ustack->uip_udp_conn->rport) &&
Packit eace71
		    (uip_ip4addr_cmp(ustack->uip_udp_conn->ripaddr,
Packit eace71
				     all_zeroes_addr4) ||
Packit eace71
		     uip_ip4addr_cmp(ustack->uip_udp_conn->ripaddr,
Packit eace71
				     all_ones_addr4) ||
Packit eace71
		     uip_ip4addr_cmp(tcp_ipv4_hdr->srcipaddr,
Packit eace71
				     ustack->uip_udp_conn->ripaddr))) {
Packit eace71
			goto udp_found;
Packit eace71
		}
Packit eace71
	}
Packit eace71
	LOG_DEBUG(PFX
Packit eace71
		  "udp: no matching connection found: dest port: %d src port: "
Packit eace71
		  "%d", udp_hdr->destport, udp_hdr->srcport);
Packit eace71
	goto drop;
Packit eace71
Packit eace71
udp_found:
Packit eace71
	ustack->uip_conn = NULL;
Packit eace71
	ustack->uip_flags = UIP_NEWDATA;
Packit eace71
	ustack->uip_sappdata = ustack->uip_appdata = ustack->network_layer +
Packit eace71
	    uip_ip_udph_len;
Packit eace71
	ustack->uip_slen = 0;
Packit eace71
	if (is_ipv6(ustack))
Packit eace71
		UIP_NDP_CALL(ustack);
Packit eace71
	else
Packit eace71
		UIP_UDP_APPCALL(ustack);
Packit eace71
udp_send:
Packit eace71
	if (ustack->uip_slen == 0)
Packit eace71
		goto drop;
Packit eace71
Packit eace71
	ustack->uip_len = ustack->uip_slen + uip_ip_udph_len;
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		goto ip_send_nolen;
Packit eace71
	} else {
Packit eace71
		tcp_ipv4_hdr->len[0] = (ustack->uip_len >> 8);
Packit eace71
		tcp_ipv4_hdr->len[1] = (ustack->uip_len & 0xff);
Packit eace71
		tcp_ipv4_hdr->ttl = ustack->uip_udp_conn->ttl;
Packit eace71
		tcp_ipv4_hdr->proto = UIP_PROTO_UDP;
Packit eace71
	}
Packit eace71
Packit eace71
	udp_hdr->udplen = htons(ustack->uip_slen + UIP_UDPH_LEN);
Packit eace71
	udp_hdr->udpchksum = 0;
Packit eace71
Packit eace71
	udp_hdr->srcport = ustack->uip_udp_conn->lport;
Packit eace71
	udp_hdr->destport = ustack->uip_udp_conn->rport;
Packit eace71
Packit eace71
	uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
Packit eace71
	uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
Packit eace71
			 ustack->uip_udp_conn->ripaddr);
Packit eace71
Packit eace71
	ustack->uip_appdata = ustack->network_layer + uip_ip_tcph_len;
Packit eace71
Packit eace71
	if (ustack->uip_buf == NULL) {
Packit eace71
		LOG_WARN(PFX "uip_buf == NULL on udp send");
Packit eace71
		goto drop;
Packit eace71
	}
Packit eace71
#if UIP_UDP_CHECKSUMS
Packit eace71
	/* Calculate UDP checksum. */
Packit eace71
	udp_hdr->udpchksum = ~(uip_udpchksum(ustack));
Packit eace71
	if (udp_hdr->udpchksum == 0)
Packit eace71
		udp_hdr->udpchksum = 0xffff;
Packit eace71
#endif /* UIP_UDP_CHECKSUMS */
Packit eace71
Packit eace71
	goto ip_send_nolen;
Packit eace71
#endif /* UIP_UDP */
Packit eace71
Packit eace71
	/* TCP input processing. */
Packit eace71
tcp_input:
Packit eace71
	++ustack->stats.tcp.recv;
Packit eace71
Packit eace71
	/* Start of TCP input header processing code. */
Packit eace71
Packit eace71
	if (uip_tcpchksum(ustack) != 0xffff) {	/* Compute and check the TCP
Packit eace71
						   checksum. */
Packit eace71
		++ustack->stats.tcp.drop;
Packit eace71
		++ustack->stats.tcp.chkerr;
Packit eace71
		LOG_WARN(PFX "tcp: bad checksum.");
Packit eace71
		goto drop;
Packit eace71
	}
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		/* Demultiplex this segment. */
Packit eace71
		/* First check any active connections. */
Packit eace71
		for (uip_connr = &ustack->uip_conns[0];
Packit eace71
		     uip_connr <= &ustack->uip_conns[UIP_CONNS - 1];
Packit eace71
		     ++uip_connr) {
Packit eace71
			if (uip_connr->tcpstateflags != UIP_CLOSED &&
Packit eace71
			    tcp_hdr->destport == uip_connr->lport &&
Packit eace71
			    tcp_hdr->srcport == uip_connr->rport &&
Packit eace71
			    uip_ip6addr_cmp(IPv6_BUF(ustack)->srcipaddr,
Packit eace71
					    uip_connr->ripaddr)) {
Packit eace71
				goto found;
Packit eace71
			}
Packit eace71
		}
Packit eace71
	} else {
Packit eace71
		/* Demultiplex this segment. */
Packit eace71
		/* First check any active connections. */
Packit eace71
		for (uip_connr = &ustack->uip_conns[0];
Packit eace71
		     uip_connr <= &ustack->uip_conns[UIP_CONNS - 1];
Packit eace71
		     ++uip_connr) {
Packit eace71
			if (uip_connr->tcpstateflags != UIP_CLOSED &&
Packit eace71
			    tcp_hdr->destport == uip_connr->lport &&
Packit eace71
			    tcp_hdr->srcport == uip_connr->rport &&
Packit eace71
			    uip_ip4addr_cmp(tcp_ipv4_hdr->srcipaddr,
Packit eace71
					    uip_connr->ripaddr)) {
Packit eace71
				goto found;
Packit eace71
			}
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* If we didn't find and active connection that expected the packet,
Packit eace71
	   either this packet is an old duplicate, or this is a SYN packet
Packit eace71
	   destined for a connection in LISTEN. If the SYN flag isn't set,
Packit eace71
	   it is an old packet and we send a RST. */
Packit eace71
	if ((tcp_hdr->flags & TCP_CTL) != TCP_SYN)
Packit eace71
		goto reset;
Packit eace71
Packit eace71
	tmp16 = tcp_hdr->destport;
Packit eace71
	/* Next, check listening connections. */
Packit eace71
	for (c = 0; c < UIP_LISTENPORTS; ++c) {
Packit eace71
		if (tmp16 == ustack->uip_listenports[c])
Packit eace71
			goto found_listen;
Packit eace71
	}
Packit eace71
Packit eace71
	/* No matching connection found, so we send a RST packet. */
Packit eace71
	++ustack->stats.tcp.synrst;
Packit eace71
reset:
Packit eace71
Packit eace71
	/* We do not send resets in response to resets. */
Packit eace71
	if (tcp_hdr->flags & TCP_RST)
Packit eace71
		goto drop;
Packit eace71
Packit eace71
	++ustack->stats.tcp.rst;
Packit eace71
Packit eace71
	tcp_hdr->flags = TCP_RST | TCP_ACK;
Packit eace71
	ustack->uip_len = uip_ip_tcph_len;
Packit eace71
	tcp_hdr->tcpoffset = 5 << 4;
Packit eace71
Packit eace71
	/* Flip the seqno and ackno fields in the TCP header. */
Packit eace71
	c = tcp_hdr->seqno[3];
Packit eace71
	tcp_hdr->seqno[3] = tcp_hdr->ackno[3];
Packit eace71
	tcp_hdr->ackno[3] = c;
Packit eace71
Packit eace71
	c = tcp_hdr->seqno[2];
Packit eace71
	tcp_hdr->seqno[2] = tcp_hdr->ackno[2];
Packit eace71
	tcp_hdr->ackno[2] = c;
Packit eace71
Packit eace71
	c = tcp_hdr->seqno[1];
Packit eace71
	tcp_hdr->seqno[1] = tcp_hdr->ackno[1];
Packit eace71
	tcp_hdr->ackno[1] = c;
Packit eace71
Packit eace71
	c = tcp_hdr->seqno[0];
Packit eace71
	tcp_hdr->seqno[0] = tcp_hdr->ackno[0];
Packit eace71
	tcp_hdr->ackno[0] = c;
Packit eace71
Packit eace71
	/* We also have to increase the sequence number we are
Packit eace71
	   acknowledging. If the least significant byte overflowed, we need
Packit eace71
	   to propagate the carry to the other bytes as well. */
Packit eace71
	if (++tcp_hdr->ackno[3] == 0) {
Packit eace71
		if (++tcp_hdr->ackno[2] == 0) {
Packit eace71
			if (++tcp_hdr->ackno[1] == 0)
Packit eace71
				++tcp_hdr->ackno[0];
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* Swap port numbers. */
Packit eace71
	tmp16 = tcp_hdr->srcport;
Packit eace71
	tcp_hdr->srcport = tcp_hdr->destport;
Packit eace71
	tcp_hdr->destport = tmp16;
Packit eace71
Packit eace71
	/* Swap IP addresses. */
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
Packit eace71
				 IPv6_BUF(ustack)->srcipaddr);
Packit eace71
		uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
Packit eace71
				 ustack->hostaddr6);
Packit eace71
	} else {
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
Packit eace71
				 tcp_ipv4_hdr->srcipaddr);
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
Packit eace71
	}
Packit eace71
Packit eace71
	/* And send out the RST packet! */
Packit eace71
	goto tcp_send_noconn;
Packit eace71
Packit eace71
	/* This label will be jumped to if we matched the incoming packet
Packit eace71
	   with a connection in LISTEN. In that case, we should create a new
Packit eace71
	   connection and send a SYNACK in return. */
Packit eace71
found_listen:
Packit eace71
	/* First we check if there are any connections avaliable. Unused
Packit eace71
	   connections are kept in the same table as used connections, but
Packit eace71
	   unused ones have the tcpstate set to CLOSED. Also, connections in
Packit eace71
	   TIME_WAIT are kept track of and we'll use the oldest one if no
Packit eace71
	   CLOSED connections are found. Thanks to Eddie C. Dost for a very
Packit eace71
	   nice algorithm for the TIME_WAIT search. */
Packit eace71
	uip_connr = 0;
Packit eace71
	for (c = 0; c < UIP_CONNS; ++c) {
Packit eace71
		if (ustack->uip_conns[c].tcpstateflags == UIP_CLOSED) {
Packit eace71
			uip_connr = &ustack->uip_conns[c];
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		if (ustack->uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
Packit eace71
			if (uip_connr == 0 ||
Packit eace71
			    ustack->uip_conns[c].timer > uip_connr->timer) {
Packit eace71
				uip_connr = &ustack->uip_conns[c];
Packit eace71
			}
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (uip_connr == 0) {
Packit eace71
		/* All connections are used already, we drop packet and hope
Packit eace71
		   that the remote end will retransmit the packet at a time when
Packit eace71
		   we have more spare connections. */
Packit eace71
		++ustack->stats.tcp.syndrop;
Packit eace71
		LOG_WARN(PFX "tcp: found no unused connections.");
Packit eace71
		goto drop;
Packit eace71
	}
Packit eace71
	ustack->uip_conn = uip_connr;
Packit eace71
Packit eace71
	/* Fill in the necessary fields for the new connection. */
Packit eace71
	uip_connr->rto = uip_connr->timer = UIP_RTO;
Packit eace71
	uip_connr->sa = 0;
Packit eace71
	uip_connr->sv = 4;
Packit eace71
	uip_connr->nrtx = 0;
Packit eace71
	uip_connr->lport = tcp_hdr->destport;
Packit eace71
	uip_connr->rport = tcp_hdr->srcport;
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		uip_ip6addr_copy(uip_connr->ripaddr,
Packit eace71
				 IPv6_BUF(ustack)->srcipaddr);
Packit eace71
	} else {
Packit eace71
		uip_ip4addr_copy(uip_connr->ripaddr, tcp_ipv4_hdr->srcipaddr);
Packit eace71
	}
Packit eace71
	uip_connr->tcpstateflags = UIP_SYN_RCVD;
Packit eace71
Packit eace71
	uip_connr->snd_nxt[0] = ustack->iss[0];
Packit eace71
	uip_connr->snd_nxt[1] = ustack->iss[1];
Packit eace71
	uip_connr->snd_nxt[2] = ustack->iss[2];
Packit eace71
	uip_connr->snd_nxt[3] = ustack->iss[3];
Packit eace71
	uip_connr->len = 1;
Packit eace71
Packit eace71
	/* rcv_nxt should be the seqno from the incoming packet + 1. */
Packit eace71
	uip_connr->rcv_nxt[3] = tcp_hdr->seqno[3];
Packit eace71
	uip_connr->rcv_nxt[2] = tcp_hdr->seqno[2];
Packit eace71
	uip_connr->rcv_nxt[1] = tcp_hdr->seqno[1];
Packit eace71
	uip_connr->rcv_nxt[0] = tcp_hdr->seqno[0];
Packit eace71
	uip_add_rcv_nxt(ustack, 1);
Packit eace71
Packit eace71
	/* Parse the TCP MSS option, if present. */
Packit eace71
	if ((tcp_hdr->tcpoffset & 0xf0) > 0x50) {
Packit eace71
		for (c = 0; c < ((tcp_hdr->tcpoffset >> 4) - 5) << 2;) {
Packit eace71
			ustack->opt =
Packit eace71
			    ustack->uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + c];
Packit eace71
			if (ustack->opt == TCP_OPT_END) {
Packit eace71
				/* End of options. */
Packit eace71
				break;
Packit eace71
			} else if (ustack->opt == TCP_OPT_NOOP) {
Packit eace71
				++c;
Packit eace71
				/* NOP option. */
Packit eace71
			} else if (ustack->opt == TCP_OPT_MSS &&
Packit eace71
				   ustack->uip_buf[uip_ip_tcph_len +
Packit eace71
						   UIP_LLH_LEN + 1 + c] ==
Packit eace71
				   TCP_OPT_MSS_LEN) {
Packit eace71
				/* An MSS option with the right option length.*/
Packit eace71
				tmp16 =
Packit eace71
				    ((u16_t) ustack->
Packit eace71
				     uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 2 +
Packit eace71
					     c] << 8) | (u16_t) ustack->
Packit eace71
				    uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 3 +
Packit eace71
					    c];
Packit eace71
				uip_connr->initialmss = uip_connr->mss =
Packit eace71
				    tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
Packit eace71
Packit eace71
				/* And we are done processing options. */
Packit eace71
				break;
Packit eace71
			} else {
Packit eace71
				/* All other options have a length field, so
Packit eace71
				   that we easily can skip past them. */
Packit eace71
				if (ustack->
Packit eace71
				    uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 1 +
Packit eace71
					    c] == 0) {
Packit eace71
					/* If the length field is zero, the
Packit eace71
					   options are malformed
Packit eace71
					   and we don't process them further. */
Packit eace71
					break;
Packit eace71
				}
Packit eace71
				c += ustack->uip_buf[uip_ip_tcph_len +
Packit eace71
						     UIP_LLH_LEN + 1 + c];
Packit eace71
			}
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* Our response will be a SYNACK. */
Packit eace71
#if UIP_ACTIVE_OPEN
Packit eace71
tcp_send_synack:
Packit eace71
	tcp_hdr->flags = TCP_ACK;
Packit eace71
Packit eace71
tcp_send_syn:
Packit eace71
	tcp_hdr->flags |= TCP_SYN;
Packit eace71
#else /* UIP_ACTIVE_OPEN */
Packit eace71
tcp_send_synack:
Packit eace71
	tcp_hdr->flags = TCP_SYN | TCP_ACK;
Packit eace71
#endif /* UIP_ACTIVE_OPEN */
Packit eace71
Packit eace71
	/* We send out the TCP Maximum Segment Size option with our
Packit eace71
	   SYNACK. */
Packit eace71
	tcp_hdr->optdata[0] = TCP_OPT_MSS;
Packit eace71
	tcp_hdr->optdata[1] = TCP_OPT_MSS_LEN;
Packit eace71
	tcp_hdr->optdata[2] = (UIP_TCP_MSS) / 256;
Packit eace71
	tcp_hdr->optdata[3] = (UIP_TCP_MSS) & 255;
Packit eace71
	ustack->uip_len = uip_ip_tcph_len + TCP_OPT_MSS_LEN;
Packit eace71
	tcp_hdr->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
Packit eace71
	goto tcp_send;
Packit eace71
Packit eace71
	/* This label will be jumped to if we found an active connection. */
Packit eace71
found:
Packit eace71
	ustack->uip_conn = uip_connr;
Packit eace71
	ustack->uip_flags = 0;
Packit eace71
	/* We do a very naive form of TCP reset processing; we just accept
Packit eace71
	   any RST and kill our connection. We should in fact check if the
Packit eace71
	   sequence number of this reset is wihtin our advertised window
Packit eace71
	   before we accept the reset. */
Packit eace71
	if (tcp_hdr->flags & TCP_RST) {
Packit eace71
		uip_connr->tcpstateflags = UIP_CLOSED;
Packit eace71
		LOG_WARN(PFX "tcp: got reset, aborting connection.");
Packit eace71
		ustack->uip_flags = UIP_ABORT;
Packit eace71
		UIP_APPCALL(ustack);
Packit eace71
		goto drop;
Packit eace71
	}
Packit eace71
	/* Calculated the length of the data, if the application has sent
Packit eace71
	   any data to us. */
Packit eace71
	c = (tcp_hdr->tcpoffset >> 4) << 2;
Packit eace71
	/* uip_len will contain the length of the actual TCP data. This is
Packit eace71
	   calculated by subtracing the length of the TCP header (in
Packit eace71
	   c) and the length of the IP header (20 bytes). */
Packit eace71
	ustack->uip_len = ustack->uip_len - c - uip_iph_len;
Packit eace71
Packit eace71
	/* First, check if the sequence number of the incoming packet is
Packit eace71
	   what we're expecting next. If not, we send out an ACK with the
Packit eace71
	   correct numbers in. */
Packit eace71
	if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
Packit eace71
	      ((tcp_hdr->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
Packit eace71
		if ((ustack->uip_len > 0
Packit eace71
		     || ((tcp_hdr->flags & (TCP_SYN | TCP_FIN)) != 0))
Packit eace71
		    && (tcp_hdr->seqno[0] != uip_connr->rcv_nxt[0]
Packit eace71
			|| tcp_hdr->seqno[1] != uip_connr->rcv_nxt[1]
Packit eace71
			|| tcp_hdr->seqno[2] != uip_connr->rcv_nxt[2]
Packit eace71
			|| tcp_hdr->seqno[3] != uip_connr->rcv_nxt[3])) {
Packit eace71
			goto tcp_send_ack;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	{
Packit eace71
		u8_t uip_acc32[4];
Packit eace71
Packit eace71
		/* Next, check if the incoming segment acks any outstanding
Packit eace71
		   data. If so, we update the sequence number, reset the len of
Packit eace71
		   the outstanding data, calc RTT estimations, and reset the
Packit eace71
		   retransmission timer. */
Packit eace71
		if ((tcp_hdr->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
Packit eace71
			uip_add32(uip_connr->snd_nxt, uip_connr->len,
Packit eace71
				  uip_acc32);
Packit eace71
Packit eace71
			if (tcp_hdr->ackno[0] == uip_acc32[0] &&
Packit eace71
			    tcp_hdr->ackno[1] == uip_acc32[1] &&
Packit eace71
			    tcp_hdr->ackno[2] == uip_acc32[2] &&
Packit eace71
			    tcp_hdr->ackno[3] == uip_acc32[3]) {
Packit eace71
				/* Update sequence number. */
Packit eace71
				uip_connr->snd_nxt[0] = uip_acc32[0];
Packit eace71
				uip_connr->snd_nxt[1] = uip_acc32[1];
Packit eace71
				uip_connr->snd_nxt[2] = uip_acc32[2];
Packit eace71
				uip_connr->snd_nxt[3] = uip_acc32[3];
Packit eace71
Packit eace71
				/* Do RTT estimation, unless we have done
Packit eace71
				   retransmissions. */
Packit eace71
				if (uip_connr->nrtx == 0) {
Packit eace71
					signed char m;
Packit eace71
					m = uip_connr->rto - uip_connr->timer;
Packit eace71
					/* This is taken directly from VJs
Packit eace71
					   original code in his paper */
Packit eace71
					m = m - (uip_connr->sa >> 3);
Packit eace71
					uip_connr->sa += m;
Packit eace71
					if (m < 0)
Packit eace71
						m = -m;
Packit eace71
					m = m - (uip_connr->sv >> 2);
Packit eace71
					uip_connr->sv += m;
Packit eace71
					uip_connr->rto =
Packit eace71
					    (uip_connr->sa >> 3) +
Packit eace71
					    uip_connr->sv;
Packit eace71
Packit eace71
				}
Packit eace71
				/* Set the acknowledged flag. */
Packit eace71
				ustack->uip_flags = UIP_ACKDATA;
Packit eace71
				/* Reset the retransmission timer. */
Packit eace71
				uip_connr->timer = uip_connr->rto;
Packit eace71
Packit eace71
				/* Reset length of outstanding data. */
Packit eace71
				uip_connr->len = 0;
Packit eace71
			}
Packit eace71
Packit eace71
		}
Packit eace71
Packit eace71
	}
Packit eace71
Packit eace71
	/* Do different things depending on in what state the connection is. */
Packit eace71
	switch (uip_connr->tcpstateflags & UIP_TS_MASK) {
Packit eace71
		/* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
Packit eace71
		   implemented, since we force the application to close when the
Packit eace71
		   peer sends a FIN (hence the application goes directly from
Packit eace71
		   ESTABLISHED to LAST_ACK). */
Packit eace71
	case UIP_SYN_RCVD:
Packit eace71
		/* In SYN_RCVD we have sent out a SYNACK in response to a SYN,
Packit eace71
		   and we are waiting for an ACK that acknowledges the data we
Packit eace71
		   sent out the last time. Therefore, we want to have the
Packit eace71
		   UIP_ACKDATA flag set.
Packit eace71
		   If so, we enter the ESTABLISHED state. */
Packit eace71
		if (ustack->uip_flags & UIP_ACKDATA) {
Packit eace71
			uip_connr->tcpstateflags = UIP_ESTABLISHED;
Packit eace71
			ustack->uip_flags = UIP_CONNECTED;
Packit eace71
			uip_connr->len = 0;
Packit eace71
			if (ustack->uip_len > 0) {
Packit eace71
				ustack->uip_flags |= UIP_NEWDATA;
Packit eace71
				uip_add_rcv_nxt(ustack, ustack->uip_len);
Packit eace71
			}
Packit eace71
			ustack->uip_slen = 0;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			goto appsend;
Packit eace71
		}
Packit eace71
		goto drop;
Packit eace71
#if UIP_ACTIVE_OPEN
Packit eace71
	case UIP_SYN_SENT:
Packit eace71
		/* In SYN_SENT, we wait for a SYNACK that is sent in response to
Packit eace71
		   our SYN. The rcv_nxt is set to sequence number in the SYNACK
Packit eace71
		   plus one, and we send an ACK. We move into the ESTABLISHED
Packit eace71
		   state. */
Packit eace71
		if ((ustack->uip_flags & UIP_ACKDATA) &&
Packit eace71
		    (tcp_hdr->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
Packit eace71
Packit eace71
			/* Parse the TCP MSS option, if present. */
Packit eace71
			if ((tcp_hdr->tcpoffset & 0xf0) > 0x50) {
Packit eace71
				for (c = 0;
Packit eace71
				     c <
Packit eace71
				     ((tcp_hdr->tcpoffset >> 4) - 5) << 2;) {
Packit eace71
					ustack->opt =
Packit eace71
					    ustack->uip_buf[uip_ip_tcph_len +
Packit eace71
							    UIP_LLH_LEN + c];
Packit eace71
					if (ustack->opt == TCP_OPT_END) {
Packit eace71
						/* End of options. */
Packit eace71
						break;
Packit eace71
					} else if (ustack->opt ==
Packit eace71
						   TCP_OPT_NOOP) {
Packit eace71
						++c;
Packit eace71
						/* NOP option. */
Packit eace71
					} else if (ustack->opt == TCP_OPT_MSS &&
Packit eace71
						   ustack->
Packit eace71
						   uip_buf[uip_ip_tcph_len +
Packit eace71
							   UIP_LLH_LEN + 1 +
Packit eace71
							   c] ==
Packit eace71
						   TCP_OPT_MSS_LEN) {
Packit eace71
						/* An MSS option with the right
Packit eace71
						   option length. */
Packit eace71
						tmp16 =
Packit eace71
						    (ustack->
Packit eace71
						     uip_buf[uip_ip_tcph_len +
Packit eace71
							     UIP_LLH_LEN + 2 +
Packit eace71
							     c] << 8) | ustack->
Packit eace71
						    uip_buf[uip_ip_tcph_len +
Packit eace71
							    UIP_LLH_LEN + 3 +
Packit eace71
							    c];
Packit eace71
						uip_connr->initialmss =
Packit eace71
						    uip_connr->mss =
Packit eace71
						    tmp16 >
Packit eace71
						    UIP_TCP_MSS ? UIP_TCP_MSS :
Packit eace71
						    tmp16;
Packit eace71
Packit eace71
						/* And we are done processing
Packit eace71
						   options. */
Packit eace71
						break;
Packit eace71
					} else {
Packit eace71
						/* All other options have a
Packit eace71
						   length field, so that we
Packit eace71
						   easily can skip past them */
Packit eace71
						if (ustack->
Packit eace71
						    uip_buf[uip_ip_tcph_len +
Packit eace71
							    UIP_LLH_LEN + 1 +
Packit eace71
							    c] == 0) {
Packit eace71
							/* If the length field
Packit eace71
							   is zero, the options
Packit eace71
							   are malformed and we
Packit eace71
							   don't process them
Packit eace71
							   further. */
Packit eace71
							break;
Packit eace71
						}
Packit eace71
						c += ustack->
Packit eace71
						    uip_buf[uip_ip_tcph_len +
Packit eace71
							    UIP_LLH_LEN + 1 +
Packit eace71
							    c];
Packit eace71
					}
Packit eace71
				}
Packit eace71
			}
Packit eace71
			uip_connr->tcpstateflags = UIP_ESTABLISHED;
Packit eace71
			uip_connr->rcv_nxt[0] = tcp_hdr->seqno[0];
Packit eace71
			uip_connr->rcv_nxt[1] = tcp_hdr->seqno[1];
Packit eace71
			uip_connr->rcv_nxt[2] = tcp_hdr->seqno[2];
Packit eace71
			uip_connr->rcv_nxt[3] = tcp_hdr->seqno[3];
Packit eace71
			uip_add_rcv_nxt(ustack, 1);
Packit eace71
			ustack->uip_flags = UIP_CONNECTED | UIP_NEWDATA;
Packit eace71
			uip_connr->len = 0;
Packit eace71
			ustack->uip_len = 0;
Packit eace71
			ustack->uip_slen = 0;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			goto appsend;
Packit eace71
		}
Packit eace71
		/* Inform the application that the connection failed */
Packit eace71
		ustack->uip_flags = UIP_ABORT;
Packit eace71
		UIP_APPCALL(ustack);
Packit eace71
		/* The connection is closed after we send the RST */
Packit eace71
		ustack->uip_conn->tcpstateflags = UIP_CLOSED;
Packit eace71
		goto reset;
Packit eace71
#endif /* UIP_ACTIVE_OPEN */
Packit eace71
Packit eace71
	case UIP_ESTABLISHED:
Packit eace71
		/* In the ESTABLISHED state, we call upon the application to
Packit eace71
		   feed data into the uip_buf. If the UIP_ACKDATA flag is set,
Packit eace71
		   the application should put new data into the buffer,
Packit eace71
		   otherwise we are retransmitting an old segment, and the
Packit eace71
		   application should put that data into the buffer.
Packit eace71
Packit eace71
		   If the incoming packet is a FIN, we should close the
Packit eace71
		   connection on this side as well, and we send out a FIN and
Packit eace71
		   enter the LAST_ACK state. We require that there is no
Packit eace71
		   outstanding data; otherwise the sequence numbers will be
Packit eace71
		   screwed up. */
Packit eace71
Packit eace71
		if (tcp_hdr->flags & TCP_FIN
Packit eace71
		    && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
Packit eace71
			if (uip_outstanding(uip_connr))
Packit eace71
				goto drop;
Packit eace71
			uip_add_rcv_nxt(ustack, 1 + ustack->uip_len);
Packit eace71
			ustack->uip_flags |= UIP_CLOSE;
Packit eace71
			if (ustack->uip_len > 0)
Packit eace71
				ustack->uip_flags |= UIP_NEWDATA;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			uip_connr->len = 1;
Packit eace71
			uip_connr->tcpstateflags = UIP_LAST_ACK;
Packit eace71
			uip_connr->nrtx = 0;
Packit eace71
tcp_send_finack:
Packit eace71
			tcp_hdr->flags = TCP_FIN | TCP_ACK;
Packit eace71
			goto tcp_send_nodata;
Packit eace71
		}
Packit eace71
Packit eace71
		/* Check the URG flag. If this is set, the segment carries
Packit eace71
		   urgent data that we must pass to the application. */
Packit eace71
		if ((tcp_hdr->flags & TCP_URG) != 0) {
Packit eace71
#if UIP_URGDATA > 0
Packit eace71
			uip_urglen = (tcp_hdr->urgp[0] << 8) | tcp_hdr->urgp[1];
Packit eace71
			if (uip_urglen > uip_len) {
Packit eace71
				/* There is more urgent data in the next segment
Packit eace71
				   to come. */
Packit eace71
				uip_urglen = uip_len;
Packit eace71
			}
Packit eace71
			uip_add_rcv_nxt(uip_urglen);
Packit eace71
			uip_len -= uip_urglen;
Packit eace71
			uip_urgdata = uip_appdata;
Packit eace71
			uip_appdata += uip_urglen;
Packit eace71
		} else {
Packit eace71
			uip_urglen = 0;
Packit eace71
#else /* UIP_URGDATA > 0 */
Packit eace71
			ustack->uip_appdata =
Packit eace71
			    ((char *)ustack->uip_appdata) +
Packit eace71
			    ((tcp_hdr->urgp[0] << 8) | tcp_hdr->urgp[1]);
Packit eace71
			ustack->uip_len -=
Packit eace71
			    (tcp_hdr->urgp[0] << 8) | tcp_hdr->urgp[1];
Packit eace71
#endif /* UIP_URGDATA > 0 */
Packit eace71
		}
Packit eace71
Packit eace71
		/* If uip_len > 0 we have TCP data in the packet, and we flag
Packit eace71
		   this by setting the UIP_NEWDATA flag and update the sequence
Packit eace71
		   number we acknowledge. If the application has stopped the
Packit eace71
		   dataflow using uip_stop(), we must not accept any data
Packit eace71
		   packets from the remote host. */
Packit eace71
		if (ustack->uip_len > 0
Packit eace71
		    && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
Packit eace71
			ustack->uip_flags |= UIP_NEWDATA;
Packit eace71
			uip_add_rcv_nxt(ustack, ustack->uip_len);
Packit eace71
		}
Packit eace71
Packit eace71
		/* Check if the available buffer space advertised by the other
Packit eace71
		   end is smaller than the initial MSS for this connection.
Packit eace71
		   If so, we set the current MSS to the window size to ensure
Packit eace71
		   that the application does not send more data than the other
Packit eace71
		   end can handle.
Packit eace71
Packit eace71
		   If the remote host advertises a zero window, we set the MSS
Packit eace71
		   to the initial MSS so that the application will send an
Packit eace71
		   entire MSS of data. This data will not be acknowledged by
Packit eace71
		   the receiver, and the application will retransmit it.
Packit eace71
		   This is called the "persistent timer" and uses the
Packit eace71
		   retransmission mechanim.
Packit eace71
		 */
Packit eace71
		tmp16 =
Packit eace71
		    ((u16_t) tcp_hdr->wnd[0] << 8) + (u16_t) tcp_hdr->wnd[1];
Packit eace71
		if (tmp16 > uip_connr->initialmss || tmp16 == 0)
Packit eace71
			tmp16 = uip_connr->initialmss;
Packit eace71
		uip_connr->mss = tmp16;
Packit eace71
Packit eace71
		/* If this packet constitutes an ACK for outstanding data
Packit eace71
		   (flagged by the UIP_ACKDATA flag, we should call the
Packit eace71
		   application since it might want to send more data.
Packit eace71
		   If the incoming packet had data from the peer
Packit eace71
		   (as flagged by the UIP_NEWDATA flag), the application
Packit eace71
		   must also be notified.
Packit eace71
Packit eace71
		   When the application is called, the global variable uip_len
Packit eace71
		   contains the length of the incoming data. The application can
Packit eace71
		   access the incoming data through the global pointer
Packit eace71
		   uip_appdata, which usually points uip_ip_tcph_len +
Packit eace71
		   UIP_LLH_LEN bytes into the uip_buf array.
Packit eace71
Packit eace71
		   If the application wishes to send any data, this data should
Packit eace71
		   be put into the uip_appdata and the length of the data should
Packit eace71
		   be put into uip_len. If the application don't have any data
Packit eace71
		   to send, uip_len must be set to 0. */
Packit eace71
		if (ustack->uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
Packit eace71
			ustack->uip_slen = 0;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
Packit eace71
appsend:
Packit eace71
Packit eace71
			if (ustack->uip_flags & UIP_ABORT) {
Packit eace71
				ustack->uip_slen = 0;
Packit eace71
				uip_connr->tcpstateflags = UIP_CLOSED;
Packit eace71
				tcp_hdr->flags = TCP_RST | TCP_ACK;
Packit eace71
				goto tcp_send_nodata;
Packit eace71
			}
Packit eace71
Packit eace71
			if (ustack->uip_flags & UIP_CLOSE) {
Packit eace71
				ustack->uip_slen = 0;
Packit eace71
				uip_connr->len = 1;
Packit eace71
				uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
Packit eace71
				uip_connr->nrtx = 0;
Packit eace71
				tcp_hdr->flags = TCP_FIN | TCP_ACK;
Packit eace71
				goto tcp_send_nodata;
Packit eace71
			}
Packit eace71
Packit eace71
			/* If uip_slen > 0, the application has data to be sent
Packit eace71
			 */
Packit eace71
			if (ustack->uip_slen > 0) {
Packit eace71
Packit eace71
				/* If the connection has acknowledged data, the
Packit eace71
				   contents of the ->len variable should be
Packit eace71
				   discarded. */
Packit eace71
				if ((ustack->uip_flags & UIP_ACKDATA) != 0)
Packit eace71
					uip_connr->len = 0;
Packit eace71
Packit eace71
				/* If the ->len variable is non-zero the
Packit eace71
				   connection has already data in transit and
Packit eace71
				   cannot send anymore right now. */
Packit eace71
				if (uip_connr->len == 0) {
Packit eace71
Packit eace71
					/* The application cannot send more than
Packit eace71
					   what is allowed by the mss (the
Packit eace71
					   minumum of the MSS and the available
Packit eace71
					   window). */
Packit eace71
					if (ustack->uip_slen > uip_connr->mss) {
Packit eace71
						ustack->uip_slen =
Packit eace71
						    uip_connr->mss;
Packit eace71
					}
Packit eace71
Packit eace71
					/* Remember how much data we send out
Packit eace71
					   now so that we know when everything
Packit eace71
					   has been acknowledged. */
Packit eace71
					uip_connr->len = ustack->uip_slen;
Packit eace71
				} else {
Packit eace71
Packit eace71
					/* If the application already had
Packit eace71
					   unacknowledged data, we make sure
Packit eace71
					   that the application does not send
Packit eace71
					   (i.e., retransmit) out more than it
Packit eace71
					   previously sent out. */
Packit eace71
					ustack->uip_slen = uip_connr->len;
Packit eace71
				}
Packit eace71
			}
Packit eace71
			uip_connr->nrtx = 0;
Packit eace71
apprexmit:
Packit eace71
			ustack->uip_appdata = ustack->uip_sappdata;
Packit eace71
Packit eace71
			/* If the application has data to be sent, or if the
Packit eace71
			   incoming packet had new data in it, we must send
Packit eace71
			   out a packet. */
Packit eace71
			if (ustack->uip_slen > 0 && uip_connr->len > 0) {
Packit eace71
				/* Add the length of the IP and TCP headers. */
Packit eace71
				ustack->uip_len =
Packit eace71
				    uip_connr->len + uip_ip_tcph_len;
Packit eace71
				/* We always set the ACK flag in response
Packit eace71
				   packets. */
Packit eace71
				tcp_hdr->flags = TCP_ACK | TCP_PSH;
Packit eace71
				/* Send the packet. */
Packit eace71
				goto tcp_send_noopts;
Packit eace71
			}
Packit eace71
			/* If there is no data to send, just send out a pure ACK
Packit eace71
			   if there is newdata. */
Packit eace71
			if (ustack->uip_flags & UIP_NEWDATA) {
Packit eace71
				ustack->uip_len = uip_ip_tcph_len;
Packit eace71
				tcp_hdr->flags = TCP_ACK;
Packit eace71
				goto tcp_send_noopts;
Packit eace71
			}
Packit eace71
		}
Packit eace71
		goto drop;
Packit eace71
	case UIP_LAST_ACK:
Packit eace71
		/* We can close this connection if the peer has acknowledged our
Packit eace71
		   FIN. This is indicated by the UIP_ACKDATA flag. */
Packit eace71
		if (ustack->uip_flags & UIP_ACKDATA) {
Packit eace71
			uip_connr->tcpstateflags = UIP_CLOSED;
Packit eace71
			ustack->uip_flags = UIP_CLOSE;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
		}
Packit eace71
		break;
Packit eace71
Packit eace71
	case UIP_FIN_WAIT_1:
Packit eace71
		/* The application has closed the connection, but the remote
Packit eace71
		   host hasn't closed its end yet. Thus we do nothing but wait
Packit eace71
		   for a FIN from the other side. */
Packit eace71
		if (ustack->uip_len > 0)
Packit eace71
			uip_add_rcv_nxt(ustack, ustack->uip_len);
Packit eace71
		if (tcp_hdr->flags & TCP_FIN) {
Packit eace71
			if (ustack->uip_flags & UIP_ACKDATA) {
Packit eace71
				uip_connr->tcpstateflags = UIP_TIME_WAIT;
Packit eace71
				uip_connr->timer = 0;
Packit eace71
				uip_connr->len = 0;
Packit eace71
			} else {
Packit eace71
				uip_connr->tcpstateflags = UIP_CLOSING;
Packit eace71
			}
Packit eace71
			uip_add_rcv_nxt(ustack, 1);
Packit eace71
			ustack->uip_flags = UIP_CLOSE;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			goto tcp_send_ack;
Packit eace71
		} else if (ustack->uip_flags & UIP_ACKDATA) {
Packit eace71
			uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
Packit eace71
			uip_connr->len = 0;
Packit eace71
			goto drop;
Packit eace71
		}
Packit eace71
		if (ustack->uip_len > 0)
Packit eace71
			goto tcp_send_ack;
Packit eace71
		goto drop;
Packit eace71
Packit eace71
	case UIP_FIN_WAIT_2:
Packit eace71
		if (ustack->uip_len > 0)
Packit eace71
			uip_add_rcv_nxt(ustack, ustack->uip_len);
Packit eace71
		if (tcp_hdr->flags & TCP_FIN) {
Packit eace71
			uip_connr->tcpstateflags = UIP_TIME_WAIT;
Packit eace71
			uip_connr->timer = 0;
Packit eace71
			uip_add_rcv_nxt(ustack, 1);
Packit eace71
			ustack->uip_flags = UIP_CLOSE;
Packit eace71
			UIP_APPCALL(ustack);
Packit eace71
			goto tcp_send_ack;
Packit eace71
		}
Packit eace71
		if (ustack->uip_len > 0)
Packit eace71
			goto tcp_send_ack;
Packit eace71
		goto drop;
Packit eace71
Packit eace71
	case UIP_TIME_WAIT:
Packit eace71
		goto tcp_send_ack;
Packit eace71
Packit eace71
	case UIP_CLOSING:
Packit eace71
		if (ustack->uip_flags & UIP_ACKDATA) {
Packit eace71
			uip_connr->tcpstateflags = UIP_TIME_WAIT;
Packit eace71
			uip_connr->timer = 0;
Packit eace71
		}
Packit eace71
	}
Packit eace71
	goto drop;
Packit eace71
Packit eace71
	/* We jump here when we are ready to send the packet, and just want
Packit eace71
	   to set the appropriate TCP sequence numbers in the TCP header. */
Packit eace71
tcp_send_ack:
Packit eace71
	tcp_hdr->flags = TCP_ACK;
Packit eace71
tcp_send_nodata:
Packit eace71
	ustack->uip_len = uip_ip_tcph_len;
Packit eace71
tcp_send_noopts:
Packit eace71
	tcp_hdr->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
Packit eace71
tcp_send:
Packit eace71
	/* We're done with the input processing. We are now ready to send a
Packit eace71
	   reply. Our job is to fill in all the fields of the TCP and IP
Packit eace71
	   headers before calculating the checksum and finally send the
Packit eace71
	   packet. */
Packit eace71
	tcp_hdr->ackno[0] = uip_connr->rcv_nxt[0];
Packit eace71
	tcp_hdr->ackno[1] = uip_connr->rcv_nxt[1];
Packit eace71
	tcp_hdr->ackno[2] = uip_connr->rcv_nxt[2];
Packit eace71
	tcp_hdr->ackno[3] = uip_connr->rcv_nxt[3];
Packit eace71
Packit eace71
	tcp_hdr->seqno[0] = uip_connr->snd_nxt[0];
Packit eace71
	tcp_hdr->seqno[1] = uip_connr->snd_nxt[1];
Packit eace71
	tcp_hdr->seqno[2] = uip_connr->snd_nxt[2];
Packit eace71
	tcp_hdr->seqno[3] = uip_connr->snd_nxt[3];
Packit eace71
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		IPv6_BUF(ustack)->proto = UIP_PROTO_TCP;
Packit eace71
		uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
Packit eace71
				 ustack->hostaddr6);
Packit eace71
		uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
Packit eace71
				 uip_connr->ripaddr6);
Packit eace71
	} else {
Packit eace71
		tcp_ipv4_hdr->proto = UIP_PROTO_TCP;
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
Packit eace71
		uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr, uip_connr->ripaddr);
Packit eace71
	}
Packit eace71
Packit eace71
	tcp_hdr->srcport = uip_connr->lport;
Packit eace71
	tcp_hdr->destport = uip_connr->rport;
Packit eace71
Packit eace71
	if (uip_connr->tcpstateflags & UIP_STOPPED) {
Packit eace71
		/* If the connection has issued uip_stop(), we advertise a zero
Packit eace71
		   window so that the remote host will stop sending data. */
Packit eace71
		tcp_hdr->wnd[0] = tcp_hdr->wnd[1] = 0;
Packit eace71
	} else {
Packit eace71
		tcp_hdr->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
Packit eace71
		tcp_hdr->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
Packit eace71
	}
Packit eace71
Packit eace71
tcp_send_noconn:
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		IPv6_BUF(ustack)->ttl = UIP_TTL;
Packit eace71
Packit eace71
		/* For IPv6, the IP length field does not include the IPv6 IP
Packit eace71
		   header length. */
Packit eace71
		IPv6_BUF(ustack)->len[0] =
Packit eace71
		    ((ustack->uip_len - uip_iph_len) >> 8);
Packit eace71
		IPv6_BUF(ustack)->len[1] =
Packit eace71
		    ((ustack->uip_len - uip_iph_len) & 0xff);
Packit eace71
	} else {
Packit eace71
		tcp_ipv4_hdr->ttl = UIP_TTL;
Packit eace71
		tcp_ipv4_hdr->len[0] = (ustack->uip_len >> 8);
Packit eace71
		tcp_ipv4_hdr->len[1] = (ustack->uip_len & 0xff);
Packit eace71
	}
Packit eace71
Packit eace71
	tcp_hdr->urgp[0] = tcp_hdr->urgp[1] = 0;
Packit eace71
Packit eace71
	/* Calculate TCP checksum. */
Packit eace71
	tcp_hdr->tcpchksum = 0;
Packit eace71
	tcp_hdr->tcpchksum = ~(uip_tcpchksum(ustack));
Packit eace71
Packit eace71
ip_send_nolen:
Packit eace71
Packit eace71
	if (!is_ipv6(ustack)) {
Packit eace71
		tcp_ipv4_hdr->vhl = 0x45;
Packit eace71
		tcp_ipv4_hdr->tos = 0;
Packit eace71
		tcp_ipv4_hdr->ipoffset[0] = tcp_ipv4_hdr->ipoffset[1] = 0;
Packit eace71
		++ustack->ipid;
Packit eace71
		tcp_ipv4_hdr->ipid[0] = ustack->ipid >> 8;
Packit eace71
		tcp_ipv4_hdr->ipid[1] = ustack->ipid & 0xff;
Packit eace71
		/* Calculate IP checksum. */
Packit eace71
		tcp_ipv4_hdr->ipchksum = 0;
Packit eace71
		tcp_ipv4_hdr->ipchksum = ~(uip_ipchksum(ustack));
Packit eace71
	}
Packit eace71
Packit eace71
	++ustack->stats.tcp.sent;
Packit eace71
send:
Packit eace71
	if (is_ipv6(ustack)) {
Packit eace71
		LOG_DEBUG(PFX "Sending packet with length %d (%d)",
Packit eace71
			  ustack->uip_len, ipv6_hdr ? ipv6_hdr->ip6_plen : 0);
Packit eace71
	} else {
Packit eace71
		LOG_DEBUG(PFX "Sending packet with length %d (%d)",
Packit eace71
			  ustack->uip_len,
Packit eace71
			  (tcp_ipv4_hdr->len[0] << 8) | tcp_ipv4_hdr->len[1]);
Packit eace71
	}
Packit eace71
	++ustack->stats.ip.sent;
Packit eace71
	/* Return and let the caller do the actual transmission. */
Packit eace71
	ustack->uip_flags = 0;
Packit eace71
	return;
Packit eace71
drop:
Packit eace71
	ustack->uip_len = 0;
Packit eace71
	ustack->uip_flags = 0;
Packit eace71
	return;
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_send(struct uip_stack *ustack, const void *data, int len)
Packit eace71
{
Packit eace71
	if (len > 0) {
Packit eace71
		ustack->uip_slen = len;
Packit eace71
		if (data != ustack->uip_buf)
Packit eace71
			memcpy(ustack->uip_buf, (data), ustack->uip_slen);
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
void uip_appsend(struct uip_stack *ustack, const void *data, int len)
Packit eace71
{
Packit eace71
	if (len > 0) {
Packit eace71
		ustack->uip_slen = len;
Packit eace71
		if (data != ustack->uip_sappdata)
Packit eace71
			memcpy(ustack->uip_sappdata, (data), ustack->uip_slen);
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
u16_t uip_datalen(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	return ustack->uip_len;
Packit eace71
}
Packit eace71
Packit eace71
/** @} */