Blame iscsiuio/src/uip/uip.c

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