uip.c
来自「FreeRTOS is a portable, open source, min」· C语言 代码 · 共 2,234 行 · 第 1/5 页
C
2,234 行
#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"
#include "uip_arp.h"
#include "FreeRTOS.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 > 0
const 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 ) };
#else
uip_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_FIXEDETHADDR
const struct uip_eth_addr uip_ethaddr = { { UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 } };
#else
struct uip_eth_addr uip_ethaddr = { { 0, 0, 0, 0, 0, 0 } };
#endif
#ifndef UIP_CONF_EXTERNAL_BUFFER
#ifdef __ICCARM__
#pragma data_alignment = 4
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */
#else
u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains incoming packets. */
#endif
#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 > 0
void *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_UDP
struct 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_OPEN
static 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 == 1
struct 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_ADD32
void uip_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_t chksum( 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_t uip_chksum( u16_t *data, u16_t len )
{
return htons( chksum(0, ( u8_t * ) data, len) );
}
/*---------------------------------------------------------------------------*/
#ifndef UIP_ARCH_IPCHKSUM
u16_t uip_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_t upper_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_IPV6
u16_t uip_icmp6chksum( void )
{
return upper_layer_chksum( UIP_PROTO_ICMP6 );
}
#endif /* UIP_CONF_IPV6 */
/*---------------------------------------------------------------------------*/
u16_t uip_tcpchksum( void )
{
return upper_layer_chksum( UIP_PROTO_TCP );
}
/*---------------------------------------------------------------------------*/
#if UIP_UDP_CHECKSUMS
u16_t uip_udpchksum( void )
{
return upper_layer_chksum( UIP_PROTO_UDP );
}
#endif /* UIP_UDP_CHECKSUMS */
#endif /* UIP_ARCH_CHKSUM */
/*---------------------------------------------------------------------------*/
void uip_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_OPEN
struct 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 )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?