📄 uip.c
字号:
#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*//** * \defgroup uip The uIP TCP/IP stack * @{ * * uIP is an implementation of the TCP/IP protocol stack intended for * small 8-bit and 16-bit microcontrollers. * * uIP provides the necessary protocols for Internet communication, * with a very small code footprint and RAM requirements - the uIP * code size is on the order of a few kilobytes and RAM usage is on * the order of a few hundred bytes. *//** * \file * The uIP TCP/IP stack code. * \author Adam Dunkels <adam@dunkels.com> *//* * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the uIP TCP/IP stack. * * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $ * *//* * uIP is a small implementation of the IP, UDP and TCP protocols (as * well as some basic ICMP stuff). The implementation couples the IP, * UDP, TCP and the application layers very tightly. To keep the size * of the compiled code down, this code frequently uses the goto * statement. While it would be possible to break the uip_process() * function into many smaller functions, this would increase the code * size because of the overhead of parameter passing and the fact that * the optimier would not be as efficient. * * The principle is that we have a small buffer, called the uip_buf, * in which the device driver puts an incoming packet. The TCP/IP * stack parses the headers in the packet, and calls the * application. If the remote host has sent data to the application, * this data is present in the uip_buf and the application read the * data from there. It is up to the application to put this data into * a byte stream if needed. The application will not be fed with data * that is out of sequence. * * If the application whishes to send data to the peer, it should put * its data into the uip_buf. The uip_appdata pointer points to the * first available byte. The TCP/IP stack will calculate the * checksums, and fill in the necessary header fields and finally send * the packet back to the peer.*/#include "uip.h"#include "uipopt.h"#include "uip_arch.h"#if UIP_CONF_IPV6#include "uip-neighbor.h"#endif /* UIP_CONF_IPV6 */#include <string.h>/*---------------------------------------------------------------------------*//* Variable definitions. *//* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */#if UIP_FIXEDADDR > 0const uip_ipaddr_t uip_hostaddr = {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};const uip_ipaddr_t uip_draddr = {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};const uip_ipaddr_t uip_netmask = {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};#elseuip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;#endif /* UIP_FIXEDADDR */static const uip_ipaddr_t all_ones_addr =#if UIP_CONF_IPV6 {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};#else /* UIP_CONF_IPV6 */ {0xffff,0xffff};#endif /* UIP_CONF_IPV6 */static const uip_ipaddr_t all_zeroes_addr =#if UIP_CONF_IPV6 {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};#else /* UIP_CONF_IPV6 */ {0x0000,0x0000};#endif /* UIP_CONF_IPV6 */#if UIP_FIXEDETHADDRconst struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5}};#elsestruct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};#endif#ifndef UIP_CONF_EXTERNAL_BUFFERu8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */#endif /* UIP_CONF_EXTERNAL_BUFFER */void *uip_appdata; /* The uip_appdata pointer points to application data. */void *uip_sappdata; /* The uip_appdata pointer points to the application data which is to be sent. */#if UIP_URGDATA > 0void *uip_urgdata; /* The uip_urgdata pointer points to urgent data (out-of-band data), if present. */u16_t uip_urglen, uip_surglen;#endif /* UIP_URGDATA > 0 */u16_t uip_len, uip_slen; /* The uip_len is either 8 or 16 bits, depending on the maximum packet size. */u8_t uip_flags; /* The uip_flags variable is used for communication between the TCP/IP stack and the application program. */struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */struct uip_conn uip_conns[UIP_CONNS]; /* The uip_conns array holds all TCP connections. */u16_t uip_listenports[UIP_LISTENPORTS]; /* The uip_listenports list all currently listning ports. */#if UIP_UDPstruct uip_udp_conn *uip_udp_conn;struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];#endif /* UIP_UDP */static u16_t ipid; /* Ths ipid variable is an increasing number that is used for the IP ID field. */void uip_setipid(u16_t id) { ipid = id; }static u8_t iss[4]; /* The iss variable is used for the TCP initial sequence number. */#if UIP_ACTIVE_OPENstatic u16_t lastport; /* Keeps track of the last port used for a new connection. */#endif /* UIP_ACTIVE_OPEN *//* Temporary variables. */u8_t uip_acc32[4];static u8_t c, opt;static u16_t tmp16;/* Structures and definitions. */#define TCP_FIN 0x01#define TCP_SYN 0x02#define TCP_RST 0x04#define TCP_PSH 0x08#define TCP_ACK 0x10#define TCP_URG 0x20#define TCP_CTL 0x3f#define TCP_OPT_END 0 /* End of TCP options list */#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */#define ICMP_ECHO_REPLY 0#define ICMP_ECHO 8#define ICMP6_ECHO_REPLY 129#define ICMP6_ECHO 128#define ICMP6_NEIGHBOR_SOLICITATION 135#define ICMP6_NEIGHBOR_ADVERTISEMENT 136#define ICMP6_FLAG_S (1 << 6)#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2/* Macros. */#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])#if UIP_STATISTICS == 1struct uip_stats uip_stat;#define UIP_STAT(s) s#else#define UIP_STAT(s)#endif /* UIP_STATISTICS == 1 */#if UIP_LOGGING == 1#include <stdio.h>void uip_log(char *msg);#define UIP_LOG(m) uip_log(m)#else#define UIP_LOG(m)#endif /* UIP_LOGGING == 1 */#if ! UIP_ARCH_ADD32voiduip_add32(u8_t *op32, u16_t op16){ uip_acc32[3] = op32[3] + (op16 & 0xff); uip_acc32[2] = op32[2] + (op16 >> 8); uip_acc32[1] = op32[1]; uip_acc32[0] = op32[0]; if(uip_acc32[2] < (op16 >> 8)) { ++uip_acc32[1]; if(uip_acc32[1] == 0) { ++uip_acc32[0]; } } if(uip_acc32[3] < (op16 & 0xff)) { ++uip_acc32[2]; if(uip_acc32[2] == 0) { ++uip_acc32[1]; if(uip_acc32[1] == 0) { ++uip_acc32[0]; } } }}#endif /* UIP_ARCH_ADD32 */#if ! UIP_ARCH_CHKSUM/*---------------------------------------------------------------------------*/static u16_tchksum(u16_t sum, const u8_t *data, u16_t len){ u16_t t; const u8_t *dataptr; const u8_t *last_byte; dataptr = data; last_byte = data + len - 1; while(dataptr < last_byte) { /* At least two more bytes */ t = (dataptr[0] << 8) + dataptr[1]; sum += t; if(sum < t) { sum++; /* carry */ } dataptr += 2; } if(dataptr == last_byte) { t = (dataptr[0] << 8) + 0; sum += t; if(sum < t) { sum++; /* carry */ } } /* Return sum in host byte order. */ return sum;}/*---------------------------------------------------------------------------*/u16_tuip_chksum(u16_t *data, u16_t len){ return htons(chksum(0, (u8_t *)data, len));}/*---------------------------------------------------------------------------*/#ifndef UIP_ARCH_IPCHKSUMu16_tuip_ipchksum(void){ u16_t sum; sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); return (sum == 0) ? 0xffff : htons(sum);}#endif/*---------------------------------------------------------------------------*/static u16_tupper_layer_chksum(u8_t proto){ u16_t upper_layer_len; u16_t sum; #if UIP_CONF_IPV6 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);#else /* UIP_CONF_IPV6 */ upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;#endif /* UIP_CONF_IPV6 */ /* First sum pseudoheader. */ /* IP protocol and length fields. This addition cannot carry. */ sum = upper_layer_len + proto; /* Sum IP source and destination addresses. */ sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); /* Sum TCP header and data. */ sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len); return (sum == 0) ? 0xffff : htons(sum);}/*---------------------------------------------------------------------------*/#if UIP_CONF_IPV6u16_tuip_icmp6chksum(void){ return upper_layer_chksum(UIP_PROTO_ICMP6); }#endif /* UIP_CONF_IPV6 *//*---------------------------------------------------------------------------*/u16_tuip_tcpchksum(void){ return upper_layer_chksum(UIP_PROTO_TCP);}/*---------------------------------------------------------------------------*/#if UIP_UDP_CHECKSUMSu16_tuip_udpchksum(void){ return upper_layer_chksum(UIP_PROTO_UDP);}#endif /* UIP_UDP_CHECKSUMS */#endif /* UIP_ARCH_CHKSUM *//*---------------------------------------------------------------------------*/voiduip_init(void){ for(c = 0; c < UIP_LISTENPORTS; ++c) { uip_listenports[c] = 0; } for(c = 0; c < UIP_CONNS; ++c) { uip_conns[c].tcpstateflags = UIP_CLOSED; }#if UIP_ACTIVE_OPEN lastport = 1024;#endif /* UIP_ACTIVE_OPEN */#if UIP_UDP for(c = 0; c < UIP_UDP_CONNS; ++c) { uip_udp_conns[c].lport = 0; }#endif /* UIP_UDP */ /* IPv4 initialization. */#if UIP_FIXEDADDR == 0 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/#endif /* UIP_FIXEDADDR */}/*---------------------------------------------------------------------------*/#if UIP_ACTIVE_OPENstruct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t rport){ register struct uip_conn *conn, *cconn; /* Find an unused local port. */ again: ++lastport; if(lastport >= 32000) { lastport = 4096; } /* Check if this port is already in use, and if so try to find another one. */ for(c = 0; c < UIP_CONNS; ++c) { conn = &uip_conns[c]; if(conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport)) { goto again; } } conn = 0; for(c = 0; c < UIP_CONNS; ++c) { cconn = &uip_conns[c]; if(cconn->tcpstateflags == UIP_CLOSED) { conn = cconn; break; } if(cconn->tcpstateflags == UIP_TIME_WAIT) { if(conn == 0 || cconn->timer > conn->timer) { conn = cconn; } } } if(conn == 0) { return 0; } conn->tcpstateflags = UIP_SYN_SENT; conn->snd_nxt[0] = iss[0]; conn->snd_nxt[1] = iss[1]; conn->snd_nxt[2] = iss[2]; conn->snd_nxt[3] = iss[3]; conn->initialmss = conn->mss = UIP_TCP_MSS; conn->len = 1; /* TCP length of the SYN is one. */ conn->nrtx = 0; conn->timer = 1; /* Send the SYN next time around. */ conn->rto = UIP_RTO; conn->sa = 0; conn->sv = 16; /* Initial value of the RTT variance. */ conn->lport = htons(lastport); conn->rport = rport; uip_ipaddr_copy(&conn->ripaddr, ripaddr); return conn;}#endif /* UIP_ACTIVE_OPEN *//*---------------------------------------------------------------------------*/#if UIP_UDPstruct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport){ register struct uip_udp_conn *conn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -