Merged from DEVEL into main tree.

This commit is contained in:
likewise
2003-11-14 13:17:23 +00:00
parent bdfdc2bb83
commit e4a6d199fe
45 changed files with 2329 additions and 850 deletions

View File

@@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -47,7 +47,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
static u16_t
lwip_chksum(void *dataptr, int len)
{
@@ -75,12 +75,12 @@ lwip_chksum(void *dataptr, int len)
return (u16_t)acc;
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
@@ -124,13 +124,13 @@ inet_chksum_pseudo(struct pbuf *p,
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
@@ -142,7 +142,7 @@ inet_chksum(void *dataptr, u16_t len)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@@ -169,7 +169,17 @@ inet_chksum_pbuf(struct pbuf *p)
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* Here for now until needed in other places in lwIP */
#ifndef isascii
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isascii(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
#define islower(c) in_range(c, 'a', 'z')
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
#endif
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
@@ -318,24 +328,24 @@ u8_t *inet_ntoa(u32_t addr)
return str;
}
/*-----------------------------------------------------------------------------------*/
#ifndef BYTE_ORDER
#error BYTE_ORDER is not defined
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
/*-----------------------------------------------------------------------------------*/
u16_t
htons(u16_t n)
{
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
/*-----------------------------------------------------------------------------------*/
u16_t
ntohs(u16_t n)
{
return htons(n);
}
/*-----------------------------------------------------------------------------------*/
u32_t
htonl(u32_t n)
{
@@ -344,11 +354,11 @@ htonl(u32_t n)
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
/*-----------------------------------------------------------------------------------*/
u32_t
ntohl(u32_t n)
{
return htonl(n);
}
/*-----------------------------------------------------------------------------------*/
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

View File

@@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet6.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -45,7 +45,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
/* chksum:
*
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
@@ -54,7 +54,7 @@
* For now, this is not optimized. Must be optimized for the particular processor
* arcitecture on which it is to run. Preferebly coded in assembler.
*/
/*-----------------------------------------------------------------------------------*/
static u32_t
chksum(void *dataptr, u16_t len)
{
@@ -74,12 +74,12 @@ chksum(void *dataptr, u16_t len)
return acc;
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
@@ -122,13 +122,13 @@ inet_chksum_pseudo(struct pbuf *p,
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
@@ -139,7 +139,7 @@ inet_chksum(void *dataptr, u16_t len)
sum += (sum >> 16);
return ~(sum & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@@ -165,4 +165,4 @@ inet_chksum_pbuf(struct pbuf *p)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -43,7 +43,7 @@
#include "lwip/stats.h"
#include "lwip/snmp.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@@ -54,9 +54,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
struct ip_addr tmpaddr;
u16_t hlen;
#ifdef ICMP_STATS
++lwip_stats.icmp.recv;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.recv);
snmp_inc_icmpinmsgs();
@@ -65,9 +63,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
}
@@ -79,9 +75,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
#ifdef ICMP_STATS
++lwip_stats.icmp.err;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
}
@@ -90,9 +84,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
@@ -101,9 +93,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
}
@@ -117,28 +107,24 @@ icmp_input(struct pbuf *p, struct netif *inp)
} else {
iecho->chksum += htons(ICMP_ECHO << 8);
}
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of echo replies attempted to send */
snmp_inc_icmpoutechoreps();
pbuf_header(p, hlen);
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
#ifdef ICMP_STATS
++lwip_stats.icmp.proterr;
++lwip_stats.icmp.drop;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.proterr);
ICMP_STATS_INC(icmp.drop);
}
pbuf_free(p);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
@@ -160,19 +146,17 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
#if IP_FORWARD
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
@@ -184,13 +168,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload;
#if ICMP_DEBUG
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
#endif /* ICMP_DEBNUG */
tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE);
@@ -202,19 +184,17 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
#endif /* IP_FORWARDING > 0 */
#endif /* IP_FORWARD */

View File

@@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -49,6 +49,7 @@
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@@ -61,23 +62,23 @@
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
ip_lookup(void *header, struct netif *inp)
@@ -106,11 +107,12 @@ ip_lookup(void *header, struct netif *inp)
#endif /* IP_OPTIONS == 0 */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
return udp_lookup(iphdr, inp);
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
#if LWIP_TCP
case IP_PROTO_TCP:
return 1;
#endif /* LWIP_TCP */
@@ -121,7 +123,7 @@ ip_lookup(void *header, struct netif *inp)
}
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It
@@ -129,7 +131,7 @@ ip_lookup(void *header, struct netif *inp)
* if the masked IP address of the network interface equals the masked
* IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
@@ -147,14 +149,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
#if IP_FORWARD
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the
* checksum and outputs the packet on the appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
@@ -199,10 +201,8 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr));
#ifdef IP_STATS
++lwip_stats.ip.fw;
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward");
@@ -210,7 +210,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
#endif /* IP_FORWARD */
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when
@@ -221,30 +221,24 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
static struct ip_hdr *iphdr;
static struct netif *netif;
static u16_t iphdrlen;
#ifdef IP_STATS
++lwip_stats.ip.recv;
#endif /* IP_STATS */
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.err;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@@ -259,10 +253,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.lenerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.lenerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@@ -271,14 +263,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.chkerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@@ -363,10 +351,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@@ -376,30 +362,31 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (iphdrlen > IP_HLEN) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */
#if LWIP_RAW
if (!raw_input(p, inp)) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
snmp_inc_ipindelivers();
udp_input(p, inp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
#if LWIP_TCP
case IP_PROTO_TCP:
snmp_inc_ipindelivers();
tcp_input(p, inp);
@@ -420,17 +407,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
#ifdef IP_STATS
++lwip_stats.ip.proterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs
@@ -438,10 +426,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
static struct ip_hdr *iphdr;
@@ -453,9 +441,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++lwip_stats.ip.err;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
@@ -467,7 +453,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id));
@@ -492,44 +478,39 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_frag(p,netif,dest);
#endif
#ifdef IP_STATS
lwip_stats.ip.xmit++;
#endif /* IP_STATS */
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* Simple interface to ip_output_if. It finds the outgoing network
* interface and calls upon ip_output_if to do the actual work.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
u8_t ttl, u8_t tos, u8_t proto)
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
return ERR_RTE;
}
return ip_output_if (p, src, dest, ttl, proto, netif);
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -573,7 +554,7 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -31,13 +31,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/sys.h"
@@ -109,9 +109,7 @@ ip_reass(struct pbuf *p)
u16_t offset, len;
u16_t i;
#ifdef IP_STATS
++lwip_stats.ip_frag.recv;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.recv);
iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload;
@@ -135,9 +133,7 @@ ip_reass(struct pbuf *p)
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
#ifdef IP_STATS
++lwip_stats.ip_frag.cachehit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.cachehit);
/* Find out the offset in the reassembly buffer where we should
copy the fragment. */
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
@@ -255,13 +251,9 @@ ip_reass(struct pbuf *p)
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
#ifdef IP_STATS
++lwip_stats.ip_frag.fw;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.fw);
} else {
#ifdef IP_STATS
++lwip_stats.ip_frag.memerr;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
@@ -269,9 +261,7 @@ ip_reass(struct pbuf *p)
}
nullreturn:
#ifdef IP_STATS
++lwip_stats.ip_frag.drop;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
@@ -347,9 +337,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
#ifdef IP_STATS
++lwip_stats.ip_frag.xmit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
left -= cop;

View File

@@ -42,7 +42,7 @@
#include "lwip/stats.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@@ -113,7 +113,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
pbuf_free(p);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
@@ -143,7 +143,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{

View File

@@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer for IPv6.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -53,24 +53,24 @@
#include "lwip/stats.h"
#include "arch/perf.h"
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It searches the
* list of network interfaces linearly. A match is found if the masked IP address of
* the network interface equals the masked IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
@@ -84,14 +84,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the packet, decrements
* the TTL value of the packet, adjusts the checksum and outputs the packet on the
* appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
{
@@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when an IP packet is
@@ -152,7 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
@@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
PERF_STOP("ip_input");
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs the IP header
* and calculates the IP header checksum. If the source IP address is NULL,
* the IP address of the outgoing network interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
@@ -311,13 +311,13 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
PERF_STOP("ip_output_if");
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* Simple interface to ip_output_if. It finds the outgoing network interface and
* calls upon ip_output_if to do the actual work.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
@@ -333,7 +333,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_output_if (p, src, dest, ttl, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -33,7 +33,7 @@
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
int
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask)
@@ -44,7 +44,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
{
@@ -53,7 +53,7 @@ ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
addr1->addr[2] == addr2->addr[2] &&
addr1->addr[3] == addr2->addr[3]);
}
/*-----------------------------------------------------------------------------------*/
void
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
{
@@ -63,7 +63,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
dest->addr[2] = src->addr[2];
dest->addr[3] = src->addr[3];*/
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_isany(struct ip_addr *addr)
{
@@ -71,7 +71,7 @@ ip_addr_isany(struct ip_addr *addr)
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
}
/*-----------------------------------------------------------------------------------*/
/*#if IP_DEBUG*/
void
ip_addr_debug_print(struct ip_addr *addr)
@@ -87,4 +87,4 @@ ip_addr_debug_print(struct ip_addr *addr)
ntohl(addr->addr[3]) & 0xffff);
}
/*#endif*/ /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -127,7 +127,7 @@ mem_init(void)
lfree = (struct mem *)ram;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */
}
@@ -148,7 +148,7 @@ mem_free(void *rmem)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
@@ -164,7 +164,7 @@ mem_free(void *rmem)
lfree = mem;
}
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */
@@ -183,7 +183,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
mem_free(rmem);
return nmem;
}
/*-----------------------------------------------------------------------------------*/
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
@@ -215,7 +215,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */
@@ -273,7 +273,7 @@ mem_malloc(mem_size_t size)
mem2->used = 0;
mem->used = 1;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
lwip_stats.mem.max = lwip_stats.mem.used;
@@ -299,7 +299,7 @@ mem_malloc(mem_size_t size)
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);

View File

@@ -36,6 +36,7 @@
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/raw.h"
#include "lwip/tcp.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
@@ -54,6 +55,7 @@ static struct memp *memp_tab[MEMP_MAX];
static const u16_t memp_sizes[MEMP_MAX] = {
sizeof(struct pbuf),
sizeof(struct raw_pcb),
sizeof(struct udp_pcb),
sizeof(struct tcp_pcb),
sizeof(struct tcp_pcb_listen),
@@ -67,6 +69,7 @@ static const u16_t memp_sizes[MEMP_MAX] = {
static const u16_t memp_num[MEMP_MAX] = {
MEMP_NUM_PBUF,
MEMP_NUM_RAW_PCB,
MEMP_NUM_UDP_PCB,
MEMP_NUM_TCP_PCB,
MEMP_NUM_TCP_PCB_LISTEN,
@@ -81,6 +84,9 @@ static const u16_t memp_num[MEMP_MAX] = {
static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct pbuf) +
sizeof(struct memp)) +
MEMP_NUM_RAW_PCB *
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
sizeof(struct memp)) +
MEMP_NUM_UDP_PCB *
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
sizeof(struct memp)) +
@@ -109,12 +115,12 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
sizeof(struct memp)))];
/*-----------------------------------------------------------------------------------*/
#if !SYS_LIGHTWEIGHT_PROT
static sys_sem_t mutex;
#endif
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
#ifndef LWIP_NOASSERT
static int
memp_sanity(void)
{
@@ -135,7 +141,7 @@ memp_sanity(void)
return 1;
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
memp_init(void)
{
@@ -143,7 +149,7 @@ memp_init(void)
u16_t i, j;
u16_t size;
#ifdef MEMP_STATS
#if MEMP_STATS
for(i = 0; i < MEMP_MAX; ++i) {
lwip_stats.memp[i].used = lwip_stats.memp[i].max =
lwip_stats.memp[i].err = 0;
@@ -176,19 +182,19 @@ memp_init(void)
}
/*-----------------------------------------------------------------------------------*/
void *
memp_malloc(memp_t type)
{
struct memp *memp;
void *mem;
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
@@ -199,13 +205,13 @@ memp_malloc(memp_t type)
if (memp != NULL) {
memp_tab[type] = memp->next;
memp->next = NULL;
#ifdef MEMP_STATS
#if MEMP_STATS
++lwip_stats.memp[type].used;
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
lwip_stats.memp[type].max = lwip_stats.memp[type].used;
}
#endif /* MEMP_STATS */
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
@@ -219,7 +225,7 @@ memp_malloc(memp_t type)
return mem;
} else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
#ifdef MEMP_STATS
#if MEMP_STATS
++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */
#if SYS_LIGHTWEIGHT_PROT
@@ -230,12 +236,12 @@ memp_malloc(memp_t type)
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
memp_free(memp_t type, void *mem)
{
struct memp *memp;
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
@@ -244,13 +250,13 @@ memp_free(memp_t type, void *mem)
}
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef MEMP_STATS
#if MEMP_STATS
lwip_stats.memp[type].used--;
#endif /* MEMP_STATS */
@@ -265,4 +271,4 @@ memp_free(memp_t type, void *mem)
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -97,7 +97,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
/* add this netif to the list */
netif->next = netif_list;
netif_list = netif;
#if NETIF_DEBUG
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
@@ -106,7 +105,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
#endif /* NETIF_DEBUG */
return netif;
}
@@ -170,7 +168,7 @@ netif_find(char *name)
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
return NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
@@ -191,7 +189,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting pcb %p\n", (void *)pcb));
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
@@ -202,8 +200,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead
* TODO: how do we know it is _listening_? */
* is set to listen to the new one instead */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
@@ -217,7 +214,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
@@ -229,7 +226,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
@@ -241,7 +238,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_default(struct netif *netif)
{
@@ -249,10 +246,10 @@ netif_set_default(struct netif *netif)
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
}
/*-----------------------------------------------------------------------------------*/
void
netif_init(void)
{
netif_list = netif_default = NULL;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -102,7 +102,7 @@ pbuf_init(void)
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
#ifdef PBUF_STATS
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
@@ -113,6 +113,7 @@ pbuf_init(void)
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
p->flags = PBUF_FLAG_POOL;
q = p;
p = p->next;
}
@@ -143,7 +144,7 @@ pbuf_pool_alloc(void)
/* Next, check the actual pbuf pool, but if the pool is locked, we
pretend to be out of buffers and return NULL. */
if (pbuf_pool_free_lock) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
return NULL;
@@ -156,7 +157,7 @@ pbuf_pool_alloc(void)
pbuf_pool = p->next;
}
#if !SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS
#if PBUF_STATS
} else {
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
@@ -164,7 +165,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS
#if PBUF_STATS
if (p != NULL) {
++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
@@ -243,7 +244,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
return NULL;
@@ -258,8 +259,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p->tot_len = length;
/* set the length of the first pbuf in the chain */
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
/* set pbuf type */
p->flags = PBUF_FLAG_POOL;
/* set reference count (needed here in case we fail) */
p->ref = 1;
@@ -274,7 +273,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q = pbuf_pool_alloc();
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
/* free chain so far allocated */
@@ -289,7 +288,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q->tot_len = rem_len;
/* this pbuf length is pool size, unless smaller sized tail */
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
q->flags = PBUF_FLAG_POOL;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
@@ -345,7 +343,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
}
#ifdef PBUF_STATS
#if PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
@@ -412,7 +410,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/* first, step over any pbufs that should remain in the chain */
rem_len = new_len;
q = p;
/* this pbuf should be kept? */
/* should this pbuf be kept? */
while (rem_len > q->len) {
/* decrease remaining length by pbuf length */
rem_len -= q->len;
@@ -511,9 +509,9 @@ pbuf_header(struct pbuf *p, s16_t header_size)
* Decrements the pbuf reference count. If it reaches
* zero, the pbuf is deallocated.
*
* For a pbuf chain, this is repeated for each pbuf in the chain, until
* a non-zero reference count is encountered, or the end of the chain is
* reached.
* For a pbuf chain, this is repeated for each pbuf in the chain, up to the
* pbuf which has a non-zero reference count after decrementing.
* (This might be the whole chain.)
*
* @param pbuf pbuf (chain) to be freed from one user.
*
@@ -619,7 +617,6 @@ pbuf_clen(struct pbuf *p)
}
/**
*
* Increment the reference count of the pbuf.
*
* @param p pbuf to increase reference counter of
@@ -638,20 +635,16 @@ pbuf_ref(struct pbuf *p)
}
/**
*
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @note May not be called on a packet queue.
*
* The ->tot_len fields of all pbufs of the head chain are adjusted.
* The ->next field of the last pbuf of the head chain is adjusted.
* The ->ref field of the first pbuf of the tail chain is adjusted.
*
* Concatenate two pbufs (each may be a pbuf chain) and take over
* the reference of the tail pbuf.
*
* @note The caller MAY NOT reference the tail pbuf afterwards.
*
* @see pbuf_chain()
*/
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
@@ -670,11 +663,31 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of h chain (p) with first of tail (t) */
/* chain last pbuf of head (p) with first of tail (t) */
p->next = t;
}
/**
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
* It's the same as pbuf_cat with the addition that it increases the reference count
* of the tail.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @note May not be called on a packet queue.
*
* The ->tot_len fields of all pbufs of the head chain are adjusted.
* The ->next field of the last pbuf of the head chain is adjusted.
* The ->ref field of the first pbuf of the tail chain is adjusted.
*
*/
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
pbuf_cat(h, t);
/* t is now referenced to one more time */
pbuf_ref(t);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)p, (void *)t));
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
/* For packet queueing. Note that queued packets must be dequeued first
@@ -711,9 +724,9 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
/* proceed to next packet on queue */
p = p->next;
}
/* chain last pbuf of h chain (p) with first of tail (t) */
/* chain last pbuf of queue with n */
p->next = n;
/* t is now referenced to one more time */
/* n is now referenced to one more time */
pbuf_ref(n);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
}
@@ -764,7 +777,7 @@ pbuf_dequeue(struct pbuf *p)
* by pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may allocate them if they become no longer referenced.
* This may deallocate them if they become no longer referenced.
*
* @param p Head of pbuf chain to process
*
@@ -889,27 +902,3 @@ pbuf_dechain(struct pbuf *p)
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q);
}
/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due
* to the new way chains are built. */
#if 0
/**
*
* Increment the reference count of all pbufs in a chain.
*
* @param p first pbuf of chain
*
*/
void
pbuf_ref_chain(struct pbuf *p)
{
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
while (p != NULL) {
++p->ref;
p = p->next;
}
SYS_ARCH_UNPROTECT(old_level);
}
#endif

310
src/core/raw.c Normal file
View File

@@ -0,0 +1,310 @@
/**
* @file
* Raw Access module
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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 lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/* raw.c
*
* The code for the Raw Access to the IP
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/raw.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include "lwip/snmp.h"
#if LWIP_RAW
/* The list of RAW PCBs */
static struct raw_pcb *raw_pcbs = NULL;
void
raw_init(void)
{
raw_pcbs = NULL;
}
/**
* Determine if in incoming IP packet is covered by a RAW pcb and
* and process it if possible
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @return 0 if packet is not eated (pbuf needs to be freed then)
* or 1 if the packet has been eaten (pbuf needs not to be freed
* then)
*
*/
int
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
int proto;
int rc = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->protocol == proto) {
if (pcb->recv) {
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
return 0;
}
pbuf_free(p);
rc = 1;
break;
}
}
return rc;
}
/**
* Bind a RAW PCB.
*
* @param pcb RAW PCB to be bound with a local address ipaddr.
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
* bind to all local interfaces.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_USE. The specified ipaddr is already bound to by
* another RAW PCB.
*
* @see raw_disconnect()
*/
err_t
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->local_ip, ipaddr);
return ERR_OK;
}
/**
* Connect an RAW PCB. This function is required by upper layers
* of lwip. Using the raw api you could use raw_send_to() instead
*
* This will associate the RAW PCB with the remote address.
*
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_send_to()
*/
err_t
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->remote_ip, ipaddr);
return ERR_OK;
}
/**
* Set the callback function if a RAW packet with the pcb's protocol
* is received. If the callback function returns a value unequal 0
* the raw packet is "eaten" and not forwarded to any other raw pcb
* including lwip itself
*/
void
raw_recv(struct raw_pcb *pcb,
int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
struct ip_addr *addr),
void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}
/**
* Send the raw IP packet to the given address. Note that actually you cannot
* modify the IP headers (this is inconsitent with the receive callback where
* you actually get the IP headers), you can only specifiy the ip payload here.
* It requires some more changes in LWIP. (there will be a raw_send() function
* then)
*
* @param pcb the raw pcb which to send
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
{
err_t err;
struct netif *netif;
struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
pbuf_header(q, -IP_HLEN);
}
if ((netif = ip_route(ipaddr)) == NULL) {
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr));
#if RAW_STATS
/* ++lwip_stats.raw.rterr;*/
#endif /* RAW_STATS */
if (q != p) {
pbuf_free(q);
}
return ERR_RTE;
}
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
} else {
/* use RAW PCB local IP address as source address */
src_ip = &(pcb->local_ip);
}
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
/* did we chain a header earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
}
return err;
}
/**
* Send the raw IP packet to the address given by raw_connect()
*
* @param pcb the raw pcb which to send
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_send_to(pcb,p,&pcb->remote_ip);
}
/**
* Remove an RAW PCB.
*
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
* RAW PCB's and the data structure is freed from memory.
*
* @see raw_new()
*/
void
raw_remove(struct raw_pcb *pcb)
{
struct raw_pcb *pcb2;
/* pcb to be removed is first in list? */
if (raw_pcbs == pcb) {
/* make list start at 2nd pcb */
raw_pcbs = raw_pcbs->next;
/* pcb not 1st in list */
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in raw_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */
pcb2->next = pcb->next;
}
}
memp_free(MEMP_RAW_PCB, pcb);
}
/**
* Create a RAW PCB.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new(u16_t proto) {
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto;
pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}
#endif /* LWIP_RAW */

View File

@@ -41,11 +41,11 @@
#if LWIP_STATS
struct stats_ lwip_stats;
/*-----------------------------------------------------------------------------------*/
void
stats_init(void)
{
memset(&lwip_stats, 0, sizeof(struct stats_));
}
#endif /* LWIP_STATS */
/*-----------------------------------------------------------------------------------*/

View File

@@ -44,7 +44,7 @@ struct sswt_cb
};
/*-----------------------------------------------------------------------------------*/
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
@@ -96,7 +96,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_sem_wait(sys_sem_t sem)
{
@@ -152,7 +152,7 @@ sys_sem_wait(sys_sem_t sem)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
@@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
/* Go through timeout list (for this task only) and remove the first matching entry,
even though the timeout has not triggered yet.
*/
/*-----------------------------------------------------------------------------------*/
void
sys_untimeout(sys_timeout_handler h, void *arg)
{
@@ -238,7 +238,7 @@ sys_untimeout(sys_timeout_handler h, void *arg)
/*-----------------------------------------------------------------------------------*/
static void
sswt_handler(void *arg)
{
@@ -252,7 +252,7 @@ sswt_handler(void *arg)
/* Wait for a semaphore with timeout (specified in ms) */
/* timeout = 0: wait forever */
/* Returns 0 on timeout. 1 otherwise */
/*-----------------------------------------------------------------------------------*/
int
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
{
@@ -279,7 +279,7 @@ sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
}
/*-----------------------------------------------------------------------------------*/
void
sys_msleep(u32_t ms)
{
@@ -289,6 +289,6 @@ sys_msleep(u32_t ms)
sys_sem_free(delaysem);
}
/*-----------------------------------------------------------------------------------*/
#endif /* NO_SYS */

View File

@@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp.c
*
* This file contains common functions for the TCP implementation, such as functinos
@@ -44,7 +44,7 @@
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -74,13 +74,13 @@ static u8_t tcp_timer;
static u16_t tcp_new_port(void);
/*-----------------------------------------------------------------------------------*/
/*
* tcp_init():
*
* Initializes the TCP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_init(void)
{
@@ -95,41 +95,34 @@ tcp_init(void)
tcp_timer = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_tmr():
*
* Called periodically to dispatch TCP timers.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_tmr(void)
{
++tcp_timer;
if (tcp_timer == 10) {
tcp_timer = 0;
}
if (tcp_timer & 1) {
/* Call tcp_fasttmr() every 200 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_fasttmr();
}
if (tcp_timer == 0 || tcp_timer == 5) {
/* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
/* Call tcp_fasttmr() every 250 ms */
tcp_fasttmr();
if (++tcp_timer & 1) {
/* Call tcp_tmr() every 500 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_slowtmr();
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_close():
*
* Closes the connection held by the PCB.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@@ -183,7 +176,7 @@ tcp_close(struct tcp_pcb *pcb)
}
return err;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_abort()
*
@@ -192,7 +185,7 @@ tcp_close(struct tcp_pcb *pcb)
* killed because of shortage of memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_abort(struct tcp_pcb *pcb)
{
@@ -240,7 +233,7 @@ tcp_abort(struct tcp_pcb *pcb)
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_bind():
*
@@ -249,16 +242,19 @@ tcp_abort(struct tcp_pcb *pcb)
* the outgoing network interface is used instead.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#ifndef SO_REUSE
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
cpcb != NULL; cpcb = cpcb->next) {
@@ -280,6 +276,102 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
}
}
}
#else /* SO_REUSE */
/* Search through list of PCB's in LISTEN state.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
can be rebound. The same applies when SOF_REUSEPORT is set.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
return ERR_USE;
}
else if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
}
}
}
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr;
}
@@ -298,7 +390,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_ABRT;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_listen():
*
@@ -308,7 +400,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
* connection to LISTEN is an irreversible process.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_listen(struct tcp_pcb *pcb)
{
@@ -325,6 +417,10 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API
@@ -333,7 +429,7 @@ tcp_listen(struct tcp_pcb *pcb)
TCP_REG(&tcp_listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_recved():
*
@@ -342,13 +438,14 @@ tcp_listen(struct tcp_pcb *pcb)
* when the data has been processed.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_recved(struct tcp_pcb *pcb, u16_t len)
{
pcb->rcv_wnd += len;
if (pcb->rcv_wnd > TCP_WND) {
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
}
if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) {
@@ -358,14 +455,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new_port():
*
* A nastly hack featuring 'goto' statements that allocates a
* new TCP local port.
*/
/*-----------------------------------------------------------------------------------*/
static u16_t
tcp_new_port(void)
{
@@ -398,7 +495,7 @@ tcp_new_port(void)
}
return port;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connect():
*
@@ -406,7 +503,7 @@ tcp_new_port(void)
* argument will be called when the connection has been established.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
@@ -453,7 +550,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_slowtmr():
*
@@ -461,7 +558,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
* removes PCBs that have been in TIME-WAIT for enough time. It also increments
* various timers such as the inactivity timer in each PCB.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_slowtmr(void)
{
@@ -527,6 +624,21 @@ tcp_slowtmr(void)
}
}
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb);
}
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
tcp_keepalive(pcb);
pcb->keep_cnt++;
}
}
/* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually
be retransmitted). */
@@ -622,13 +734,13 @@ tcp_slowtmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_fasttmr():
*
* Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_fasttmr(void)
{
@@ -643,75 +755,72 @@ tcp_fasttmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_segs_free():
*
* Deallocates a list of TCP segments (tcp_seg structures).
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
u8_t count = 0;
struct tcp_seg *next;
again:
if (seg != NULL) {
while (seg != NULL) {
next = seg->next;
count += tcp_seg_free(seg);
seg = next;
goto again;
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_seg_free():
*
* Frees a TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_seg_free(struct tcp_seg *seg)
{
u8_t count = 0;
if (seg != NULL) {
if (seg->p == NULL) {
memp_free(MEMP_TCP_SEG, seg);
} else {
if (seg->p != NULL) {
count = pbuf_free(seg->p);
#if TCP_DEBUG
seg->p = NULL;
#endif /* TCP_DEBUG */
memp_free(MEMP_TCP_SEG, seg);
}
memp_free(MEMP_TCP_SEG, seg);
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_setprio():
*
* Sets the priority of a connection.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{
pcb->prio = prio;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_QUEUE_OOSEQ
/*
* tcp_seg_copy():
*
* Returns a copy of the given TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_seg *
tcp_seg_copy(struct tcp_seg *seg)
{
@@ -725,7 +834,8 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p);
return cseg;
}
/*-----------------------------------------------------------------------------------*/
#endif
#if LWIP_CALLBACK_API
static err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
@@ -739,7 +849,7 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_prio(u8_t prio)
{
@@ -770,7 +880,7 @@ tcp_kill_prio(u8_t prio)
}
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_timewait(void)
{
@@ -792,8 +902,8 @@ tcp_kill_timewait(void)
}
}
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_alloc(u8_t prio)
{
@@ -817,6 +927,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0;
@@ -836,10 +948,14 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new():
*
@@ -847,13 +963,13 @@ tcp_alloc(u8_t prio)
* any of the TCP PCB lists.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_new(void)
{
return tcp_alloc(TCP_PRIO_NORMAL);
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_arg():
*
@@ -861,13 +977,14 @@ tcp_new(void)
* functions.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_arg(struct tcp_pcb *pcb, void *arg)
{
pcb->callback_arg = arg;
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
/*
* tcp_recv():
*
@@ -875,16 +992,14 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
* connection receives data.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
{
pcb->recv = recv;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_sent():
*
@@ -892,16 +1007,14 @@ tcp_recv(struct tcp_pcb *pcb,
* has been successfully delivered to the remote host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
{
pcb->sent = sent;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_err():
*
@@ -909,16 +1022,31 @@ tcp_sent(struct tcp_pcb *pcb,
* has occured on the connection.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_err(struct tcp_pcb *pcb,
void (* errf)(void *arg, err_t err))
{
pcb->errf = errf;
}
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_poll():
*
@@ -927,7 +1055,7 @@ tcp_err(struct tcp_pcb *pcb,
* timer interval, which is called twice a second.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
@@ -937,31 +1065,14 @@ tcp_poll(struct tcp_pcb *pcb,
#endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_purge():
*
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_purge(struct tcp_pcb *pcb)
{
@@ -996,14 +1107,14 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
NULL;
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_remove():
*
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
{
@@ -1022,14 +1133,14 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_next_iss():
*
* Calculates a new initial sequence number for new connections.
*
*/
/*-----------------------------------------------------------------------------------*/
u32_t
tcp_next_iss(void)
{
@@ -1038,31 +1149,31 @@ tcp_next_iss(void)
iss += tcp_ticks; /* XXX */
return iss;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void
tcp_debug_print(struct tcp_hdr *tcphdr)
{
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n",
tcphdr->src, tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (seq no)\n",
tcphdr->seqno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n",
tcphdr->ackno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u| %5u | (offset, flags (",
TCPH_OFFSET(tcphdr),
TCPH_FLAGS(tcphdr) >> 4 & 1,
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
TCPH_HDRLEN(tcphdr),
TCPH_FLAGS(tcphdr) >> 5 & 1,
TCPH_FLAGS(tcphdr) >> 4 & 1,
TCPH_FLAGS(tcphdr) >> 3 & 1,
TCPH_FLAGS(tcphdr) >> 2 & 1,
TCPH_FLAGS(tcphdr) >> 1 & 1,
TCPH_FLAGS(tcphdr) & 1,
tcphdr->wnd));
ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@@ -1070,7 +1181,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_state(enum tcp_state s)
{
@@ -1111,7 +1222,7 @@ tcp_debug_print_state(enum tcp_state s)
break;
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_flags(u8_t flags)
{
@@ -1133,8 +1244,14 @@ tcp_debug_print_flags(u8_t flags)
if (flags & TCP_URG) {
LWIP_DEBUGF(TCP_DEBUG, ("URG "));
}
if (flags & TCP_ECE) {
LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
}
if (flags & TCP_CWR) {
LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_pcbs(void)
{
@@ -1161,7 +1278,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
}
/*-----------------------------------------------------------------------------------*/
int
tcp_pcbs_sane(void)
{
@@ -1178,7 +1295,7 @@ tcp_pcbs_sane(void)
}
#endif /* TCP_DEBUG */
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_input.c
*
* The input processing functions of TCP.
@@ -45,7 +45,7 @@
* tcp_process() -> tcp_receive() (-> application).
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@@ -85,7 +85,7 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
/* tcp_input:
*
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
@@ -93,34 +93,38 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
* the TCP finite state machine. This function is called by the IP layer (in
* ip_input()).
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_input(struct pbuf *p, struct netif *inp)
{
struct tcp_pcb *pcb, *prev;
struct tcp_pcb_listen *lpcb;
u8_t offset;
u8_t hdrlen;
err_t err;
#ifdef SO_REUSE
struct tcp_pcb *pcb_temp;
int reuse = 0;
int reuse_port = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef TCP_STATS
++lwip_stats.tcp.recv;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.recv);
iphdr = p->payload;
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
#if TCP_INPUT_DEBUG
tcp_debug_print(tcphdr);
#endif
/* remove header from payload */
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
/* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
#ifdef TCP_STATS
++lwip_stats.tcp.lenerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.lenerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
}
@@ -142,10 +146,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if TCP_DEBUG
tcp_debug_print(tcphdr);
#endif /* TCP_DEBUG */
#ifdef TCP_STATS
++lwip_stats.tcp.chkerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.chkerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
@@ -154,8 +156,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */
offset = TCPH_OFFSET(tcphdr) >> 4;
pbuf_header(p, -(offset * 4));
hdrlen = TCPH_HDRLEN(tcphdr);
pbuf_header(p, -(hdrlen * 4));
/* Convert fields in TCP header to host byte order. */
tcphdr->src = ntohs(tcphdr->src);
@@ -170,7 +172,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Demultiplex an incoming segment. First, we check if it is destined
for an active connection. */
prev = NULL;
#ifdef SO_REUSE
pcb_temp = tcp_active_pcbs;
again_1:
/* Iterate through the TCP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
@@ -179,6 +191,32 @@ tcp_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port = 1;
p->ref++;
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
/* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment
arrivals). */
@@ -323,33 +361,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */
#endif /* TCP_INPUT_DEBUG */
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
reuse_port = 0;
/* We are searching connected sockets */
goto again_1;
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
/* If no matching PCB was found, send a TCP RST (reset) to the
sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
#ifdef TCP_STATS
++lwip_stats.tcp.proterr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.proterr);
TCP_STATS_INC(tcp.drop);
tcp_rst(ackno, seqno + tcplen,
&(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src);
}
pbuf_free(p);
}
#ifdef SO_REUSE
end:
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
PERF_STOP("tcp_input");
}
/*-----------------------------------------------------------------------------------*/
/* tcp_listen_input():
*
* Called by tcp_input() when a segment arrives for a listening
* connection.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
@@ -373,9 +428,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
SYN at a time when we have more memory available. */
if (npcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
return ERR_MEM;
}
/* Set up the new PCB. */
@@ -387,12 +440,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->rcv_nxt = seqno + 1;
npcb->snd_wnd = tcphdr->wnd;
npcb->ssthresh = npcb->snd_wnd;
npcb->snd_wl1 = seqno;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API
npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
/* inherit socket options */
npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
/* Register the new PCB so that we can begin receiving segments
for it. */
TCP_REG(&tcp_active_pcbs, npcb);
@@ -411,13 +465,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_timewait_input():
*
* Called by tcp_input() when a segment arrives for a connection in
* TIME_WAIT.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_timewait_input(struct tcp_pcb *pcb)
{
@@ -429,7 +483,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
}
return tcp_output(pcb);
}
/*-----------------------------------------------------------------------------------*/
/* tcp_process
*
* Implements the TCP state machine. Called by tcp_input. In some
@@ -437,7 +491,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
* argument will be freed by the caller (tcp_input()) unless the
* recv_data pointer in the pcb is set.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_process(struct tcp_pcb *pcb)
{
@@ -479,6 +533,7 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0;
/* Do different things depending on the TCP state. */
switch (pcb->state) {
@@ -489,7 +544,8 @@ tcp_process(struct tcp_pcb *pcb)
ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
pcb->rcv_nxt = seqno + 1;
pcb->lastack = ackno;
pcb->snd_wnd = pcb->snd_wl1 = tcphdr->wnd;
pcb->snd_wnd = tcphdr->wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED;
pcb->cwnd = pcb->mss;
--pcb->snd_queuelen;
@@ -594,7 +650,7 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_receive:
*
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
@@ -606,7 +662,7 @@ tcp_process(struct tcp_pcb *pcb)
* If the incoming segment constitutes an ACK for a segment that was used for RTT
* estimation, the RTT is estimated here as well.
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_receive(struct tcp_pcb *pcb)
{
@@ -934,7 +990,7 @@ tcp_receive(struct tcp_pcb *pcb)
inseg.p = NULL;
}
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@@ -957,15 +1013,14 @@ tcp_receive(struct tcp_pcb *pcb)
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
if (recv_data) {
pbuf_chain(recv_data, cseg->p);
pbuf_free(cseg->p);
pbuf_cat(recv_data, cseg->p);
} else {
recv_data = cseg->p;
}
cseg->p = NULL;
}
if (flags & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@@ -1103,7 +1158,7 @@ tcp_receive(struct tcp_pcb *pcb)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_parseopt:
*
@@ -1111,7 +1166,7 @@ tcp_receive(struct tcp_pcb *pcb)
* from uIP with only small changes.)
*
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_parseopt(struct tcp_pcb *pcb)
{
@@ -1122,8 +1177,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
opts = (u8_t *)tcphdr + TCP_HLEN;
/* Parse the TCP MSS option, if present. */
if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
if(TCPH_HDRLEN(tcphdr) > 0x5) {
for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
opt = opts[c];
if (opt == 0x00) {
/* End of options. */
@@ -1153,5 +1208,5 @@ tcp_parseopt(struct tcp_pcb *pcb)
}
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_output.c
*
* The output functions of TCP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@@ -64,14 +64,14 @@
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
@@ -90,7 +90,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
return ERR_CONN;
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy,
@@ -154,12 +154,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->p = NULL;
if (queue == NULL) {
queue = seg;
useg = queue = seg;
}
else {
/* Attach the segment to the end of the queued segments. */
for (useg = queue; useg->next != NULL; useg = useg->next);
useg->next = seg;
useg = seg;
}
/* If copy is set, memory should be allocated
@@ -210,9 +210,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p);
pbuf_free(p);
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p, p);
p = NULL;
}
@@ -234,9 +233,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.err);
goto memerr;
}
seg->tcphdr = seg->p->payload;
@@ -249,10 +246,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Copy the options into the header, if they are present. */
if (optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
TCPH_HDRLEN_SET(seg->tcphdr, 5);
}
else {
TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
/* Copy options into data portion of segment.
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
@@ -288,11 +285,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p);
/* Free buffer which was merged. Note that the previous pbuf_chain call
* will have incremented the ref count, so here the ref count will still
* be 1 for the 1 pointer still being used on this buffer. */
pbuf_free(queue->p);
pbuf_cat(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
@@ -327,14 +320,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
return ERR_OK;
memerr:
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
tcp_segs_free(queue);
@@ -347,7 +338,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
/* find out what we can send and send it */
err_t
tcp_output(struct tcp_pcb *pcb)
@@ -373,6 +364,13 @@ tcp_output(struct tcp_pcb *pcb)
seg = pcb->unsent;
/* useg should point to last segment on unacked queue */
useg = pcb->unacked;
if (useg != NULL) {
for (; useg->next != NULL; useg = useg->next);
}
/* If the TF_ACK_NOW flag is set, we check if there is data that is
to be sent. If data is to be sent out, we'll just piggyback our
acknowledgement with the outgoing segment. If no data will be
@@ -398,13 +396,14 @@ tcp_output(struct tcp_pcb *pcb)
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
pbuf_free(p);
@@ -443,7 +442,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
@@ -457,11 +456,10 @@ tcp_output(struct tcp_pcb *pcb)
seg->next = NULL;
if (pcb->unacked == NULL) {
pcb->unacked = seg;
useg = seg;
} else {
for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg;
useg = useg->next;
}
} else {
tcp_seg_free(seg);
@@ -470,7 +468,7 @@ tcp_output(struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
@@ -523,14 +521,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
&(pcb->local_ip),
&(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.xmit);
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rst(u32_t seqno, u32_t ackno,
struct ip_addr *local_ip, struct ip_addr *remote_ip,
@@ -552,20 +548,19 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rexmit(struct tcp_pcb *pcb)
{
@@ -595,6 +590,48 @@ tcp_rexmit(struct tcp_pcb *pcb)
tcp_output(pcb);
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
return;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

View File

@@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* udp.c
*
* The code for the User Datagram Protocol UDP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/def.h"
@@ -64,24 +64,20 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
udp_init(void)
{
udp_pcbs = pcb_cache = NULL;
}
/*-----------------------------------------------------------------------------------*/
/* udp_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
@@ -163,21 +159,24 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
#ifdef SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
int reuse_port_2 = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef UDP_STATS
++lwip_stats.udp.recv;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.recv);
iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
#ifdef UDP_STATS
++lwip_stats.udp.lenerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -190,9 +189,7 @@ udp_input(struct pbuf *p, struct netif *inp)
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
#if UDP_DEBUG
udp_debug_print(udphdr);
#endif /* UDP_DEBUG */
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
@@ -200,8 +197,18 @@ udp_input(struct pbuf *p, struct netif *inp)
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_1:
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
@@ -221,6 +228,27 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_1 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
@@ -228,7 +256,16 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) {
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@@ -242,7 +279,28 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_2 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
}
@@ -262,10 +320,8 @@ udp_input(struct pbuf *p, struct netif *inp)
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -277,10 +333,8 @@ udp_input(struct pbuf *p, struct netif *inp)
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -291,7 +345,33 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb != NULL) {
snmp_inc_udpindatagrams();
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
if(reuse_port_1) {
/* We are searching connected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_1;
} else {
/* We are searching unconnected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_2;
}
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
@@ -304,10 +384,8 @@ udp_input(struct pbuf *p, struct netif *inp)
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT);
}
#ifdef UDP_STATS
++lwip_stats.udp.proterr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.proterr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpnoports();
pbuf_free(p);
}
@@ -380,9 +458,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* using IP_ANY_ADDR? */
@@ -407,7 +483,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
err = ip_output_if (p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
snmp_inc_udpoutdatagrams();
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@@ -422,7 +498,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);
err = ip_output_if(p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
}
/* did we chain a header earlier? */
@@ -431,9 +507,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
pbuf_free(q);
}
#ifdef UDP_STATS
++lwip_stats.udp.xmit;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.xmit);
return err;
}
@@ -457,9 +531,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -470,6 +548,8 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
/* pcb already in list, just rebind */
rebind = 1;
}
#ifndef SO_REUSE
/* this code does not allow upper layer to share a UDP port for
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
@@ -486,8 +566,52 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
return ERR_USE;
}
#endif
#else /* SO_REUSE */
/* Search through list of PCB's.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
else if (ipcb->local_port == port) {
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
}
}
#endif /* SO_REUSE */
}
/* bind local address */
#ifdef SO_REUSE
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
@@ -559,9 +683,7 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/** TODO: this will bind the udp pcb locally, to the interface which
@@ -596,7 +718,7 @@ udp_disconnect(struct udp_pcb *pcb)
{
pcb->flags &= ~UDP_FLAGS_CONNECTED;
}
/*-----------------------------------------------------------------------------------*/
void
udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@@ -650,9 +772,12 @@ udp_new(void) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb));
}
pcb->ttl = UDP_TTL;
return pcb;
}
/*-----------------------------------------------------------------------------------*/
#if UDP_DEBUG
int
udp_debug_print(struct udp_hdr *udphdr)
@@ -668,7 +793,7 @@ udp_debug_print(struct udp_hdr *udphdr)
return 0;
}
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_UDP */