mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2026-08-10 17:43:39 +08:00
Combined IPv4 and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP code so that the code is more readable.
This commit is contained in:
@@ -257,30 +257,13 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
* IP addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ip address (used for checksum of pseudo header)
|
||||
* @param dst destination ip address (used for checksum of pseudo header)
|
||||
* @param proto ip protocol (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
||||
static u16_t
|
||||
inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u8_t swapped = 0;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
@@ -300,12 +283,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
@@ -330,18 +308,63 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||
inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||
ip_addr_t *src, ip_addr_t *dest)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc = (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
|
||||
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||
ip6_addr_t *src, ip6_addr_t *dest)
|
||||
{
|
||||
u32_t acc = 0;
|
||||
u32_t addr;
|
||||
u8_t addr_part;
|
||||
|
||||
for (addr_part = 0; addr_part < 4; addr_part++) {
|
||||
addr = src->addr[addr_part];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[addr_part];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
|
||||
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
||||
static u16_t
|
||||
inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||
u16_t chksum_len, u32_t acc)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u8_t swapped = 0;
|
||||
u16_t chklen;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
@@ -366,12 +389,7 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
@@ -383,6 +401,70 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum_pseudo_partial:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
* IP addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ip address (used for checksum of pseudo header)
|
||||
* @param dst destination ip address (used for checksum of pseudo header)
|
||||
* @param proto ip protocol (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||
u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc = (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
|
||||
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order. Will only compute for a
|
||||
* portion of the payload.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @param chksum_len number of payload bytes used to compute chksum
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||
u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest)
|
||||
{
|
||||
u32_t acc = 0;
|
||||
u32_t addr;
|
||||
u8_t addr_part;
|
||||
|
||||
for (addr_part = 0; addr_part < 4; addr_part++) {
|
||||
addr = src->addr[addr_part];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[addr_part];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
|
||||
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Functions common to all TCP/IPv4 modules, such as the byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 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>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
||||
@@ -93,20 +93,8 @@
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
/**
|
||||
* The interface that provided the packet for the current callback
|
||||
* invocation.
|
||||
*/
|
||||
struct netif *current_netif;
|
||||
|
||||
/**
|
||||
* Header of the input packet currently being processed.
|
||||
*/
|
||||
const struct ip_hdr *current_header;
|
||||
/** Source IP address of current_header */
|
||||
ip_addr_t current_iphdr_src;
|
||||
/** Destination IP address of current_header */
|
||||
ip_addr_t current_iphdr_dest;
|
||||
/** Global data for both IPv4 and IPv6 */
|
||||
struct ip_globals ip_data;
|
||||
|
||||
/** The IP header ID of the next outgoing IP packet */
|
||||
static u16_t ip_id;
|
||||
@@ -164,19 +152,19 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
PERF_START;
|
||||
|
||||
/* RFC3927 2.7: do not forward link-local addresses */
|
||||
if (ip_addr_islinklocal(¤t_iphdr_dest)) {
|
||||
if (ip_addr_islinklocal(ip_current_dest_addr())) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||
goto return_noroute;
|
||||
}
|
||||
|
||||
/* Find network interface where to forward this IP packet to. */
|
||||
netif = ip_route(¤t_iphdr_dest);
|
||||
netif = ip_route(ip_current_dest_addr());
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||
goto return_noroute;
|
||||
}
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
@@ -208,8 +196,8 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||
|
||||
IP_STATS_INC(ip.fw);
|
||||
IP_STATS_INC(ip.xmit);
|
||||
@@ -217,7 +205,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
|
||||
PERF_STOP("ip_forward");
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, ¤t_iphdr_dest);
|
||||
netif->output(netif, p, ip_current_dest_addr());
|
||||
return;
|
||||
return_noroute:
|
||||
snmp_inc_ipoutnoroutes();
|
||||
@@ -311,13 +299,13 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
pbuf_realloc(p, iphdr_len);
|
||||
|
||||
/* copy IP addresses to aligned ip_addr_t */
|
||||
ip_addr_copy(current_iphdr_dest, iphdr->dest);
|
||||
ip_addr_copy(current_iphdr_src, iphdr->src);
|
||||
ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest);
|
||||
ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src);
|
||||
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
#if LWIP_IGMP
|
||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_iphdr_dest))) {
|
||||
if (ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip_current_dest_addr()))) {
|
||||
netif = inp;
|
||||
} else {
|
||||
netif = NULL;
|
||||
@@ -340,9 +328,9 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(¤t_iphdr_dest, &(netif->ip_addr)) ||
|
||||
if (ip_addr_cmp(ip_current_dest_addr(), &(netif->ip_addr)) ||
|
||||
/* or broadcast on this interface network address? */
|
||||
ip_addr_isbroadcast(¤t_iphdr_dest, netif)) {
|
||||
ip_addr_isbroadcast(ip_current_dest_addr(), netif)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
@@ -352,7 +340,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
/* connections to link-local addresses must persist after changing
|
||||
the netif's address (RFC3927 ch. 1.9) */
|
||||
if ((netif->autoip != NULL) &&
|
||||
ip_addr_cmp(¤t_iphdr_dest, &(netif->autoip->llipaddr))) {
|
||||
ip_addr_cmp(ip_current_dest_addr(), &(netif->autoip->llipaddr))) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
@@ -400,10 +388,10 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
|
||||
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
||||
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
|
||||
if (check_ip_src && !ip_addr_isany(¤t_iphdr_src))
|
||||
if (check_ip_src && !ip_addr_isany(ip_current_src_addr()))
|
||||
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
||||
{ if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) ||
|
||||
(ip_addr_ismulticast(¤t_iphdr_src))) {
|
||||
{ if ((ip_addr_isbroadcast(ip_current_src_addr(), inp)) ||
|
||||
(ip_addr_ismulticast(ip_current_src_addr()))) {
|
||||
/* packet source is not valid */
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
|
||||
/* free (drop) packet pbufs */
|
||||
@@ -421,7 +409,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* non-broadcast packet? */
|
||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
||||
if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp)) {
|
||||
/* try to forward IP packet on (other) interfaces */
|
||||
ip_forward(p, iphdr, inp);
|
||||
} else
|
||||
@@ -480,8 +468,9 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
ip_debug_print(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||
|
||||
current_netif = inp;
|
||||
current_header = iphdr;
|
||||
ip_data.current_netif = inp;
|
||||
ip_data.current_ip4_header = iphdr;
|
||||
ip_data.current_ip_header_tot_len = IPH_LEN(iphdr);
|
||||
|
||||
#if LWIP_RAW
|
||||
/* raw input did not eat the packet? */
|
||||
@@ -517,14 +506,14 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
#if LWIP_IGMP
|
||||
case IP_PROTO_IGMP:
|
||||
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||
igmp_input(p, inp, ¤t_iphdr_dest);
|
||||
igmp_input(p, inp, ip_current_dest_addr());
|
||||
break;
|
||||
#endif /* LWIP_IGMP */
|
||||
default:
|
||||
#if LWIP_ICMP
|
||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp) &&
|
||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) &&
|
||||
!ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
}
|
||||
@@ -539,10 +528,12 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
}
|
||||
|
||||
current_netif = NULL;
|
||||
current_header = NULL;
|
||||
ip_addr_set_any(¤t_iphdr_src);
|
||||
ip_addr_set_any(¤t_iphdr_dest);
|
||||
/* @todo: this is not really necessary... */
|
||||
ip_data.current_netif = NULL;
|
||||
ip_data.current_ip4_header = NULL;
|
||||
ip_data.current_ip_header_tot_len = 0;
|
||||
ip_addr_set_any(ip_current_src_addr());
|
||||
ip_addr_set_any(ip_current_dest_addr());
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -805,9 +796,9 @@ ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
NETIF_SET_HWADDRHINT(netif, addr_hint);
|
||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
netif->addr_hint = NULL;
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -48,13 +48,13 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp6.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ETHTYPE_IPV6 0x86dd
|
||||
#define ETHTYPE_IPV6 0x86DD
|
||||
|
||||
/** The ethernet address */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
@@ -89,7 +89,30 @@ PACK_STRUCT_END
|
||||
|
||||
#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
|
||||
|
||||
static err_t ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst);
|
||||
/**
|
||||
* Send an IPv6 packet on the network using netif->linkoutput
|
||||
* The ethernet header is filled in before sending.
|
||||
*
|
||||
* @params netif the lwIP network interface on which to send the packet
|
||||
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
||||
* @params src the source MAC address to be copied into the ethernet header
|
||||
* @params dst the destination MAC address to be copied into the ethernet header
|
||||
* @return ERR_OK if the packet was sent, any other err_t on failure
|
||||
*/
|
||||
static err_t
|
||||
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
||||
{
|
||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
||||
(netif->hwaddr_len == 6));
|
||||
SMEMCPY(ðhdr->dest, dst, 6);
|
||||
SMEMCPY(ðhdr->src, src, 6);
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
||||
/* send the packet */
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
||||
@@ -169,29 +192,4 @@ ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an IPv6 packet on the network using netif->linkoutput
|
||||
* The ethernet header is filled in before sending.
|
||||
*
|
||||
* @params netif the lwIP network interface on which to send the packet
|
||||
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
||||
* @params src the source MAC address to be copied into the ethernet header
|
||||
* @params dst the destination MAC address to be copied into the ethernet header
|
||||
* @return ERR_OK if the packet was sent, any other err_t on failure
|
||||
*/
|
||||
static err_t
|
||||
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
||||
{
|
||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
||||
(netif->hwaddr_len == 6));
|
||||
SMEMCPY(ðhdr->dest, dst, 6);
|
||||
SMEMCPY(ðhdr->src, src, 6);
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
||||
/* send the packet */
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/nd6.h"
|
||||
@@ -63,7 +63,7 @@
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
static void icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data);
|
||||
static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
|
||||
|
||||
|
||||
/**
|
||||
@@ -96,8 +96,8 @@ icmp6_input(struct pbuf *p, struct netif *inp)
|
||||
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
||||
|
||||
#if LWIP_ICMP6_CHECKSUM_CHECK
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_ICMP6, p->tot_len) != 0) {
|
||||
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
|
||||
ip6_current_dest_addr()) != 0) {
|
||||
/* Checksum failed */
|
||||
pbuf_free(p);
|
||||
ICMP6_STATS_INC(icmp6.chkerr);
|
||||
@@ -171,8 +171,7 @@ icmp6_input(struct pbuf *p, struct netif *inp)
|
||||
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
||||
reply_src, ip6_current_src_addr(),
|
||||
IP6_NEXTH_ICMP6, r->tot_len);
|
||||
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
|
||||
|
||||
/* Send reply. */
|
||||
ICMP6_STATS_INC(icmp6.xmit);
|
||||
@@ -201,7 +200,7 @@ icmp6_input(struct pbuf *p, struct netif *inp)
|
||||
void
|
||||
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_DUR, c, 0);
|
||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +213,7 @@ icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
||||
void
|
||||
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_PTB, 0, mtu);
|
||||
icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,7 +226,7 @@ icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
||||
void
|
||||
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_TE, c, 0);
|
||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,7 +240,7 @@ icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
||||
void
|
||||
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_PP, c, pointer);
|
||||
icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,12 +248,12 @@ icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
||||
*
|
||||
* @param p the input packet for which the response should be sent,
|
||||
* p->payload pointing to the IPv6 header
|
||||
* @param type Type of the ICMPv6 header
|
||||
* @param code Code of the ICMPv6 header
|
||||
* @param data Additional 32-bit parameter in the ICMPv6 header
|
||||
* @param type Type of the ICMPv6 header
|
||||
*/
|
||||
static void
|
||||
icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data)
|
||||
icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct icmp6_hdr *icmp6hdr;
|
||||
@@ -281,7 +280,7 @@ icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data)
|
||||
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
||||
|
||||
/* Select an address to use as source. */
|
||||
reply_src = ip6_select_source_address(current_netif, ip6_current_src_addr());
|
||||
reply_src = ip6_select_source_address(ip_current_netif(), ip6_current_src_addr());
|
||||
if (reply_src == NULL) {
|
||||
/* drop */
|
||||
pbuf_free(q);
|
||||
@@ -291,13 +290,12 @@ icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data)
|
||||
|
||||
/* calculate checksum */
|
||||
icmp6hdr->chksum = 0;
|
||||
icmp6hdr->chksum = ip6_chksum_pseudo(q, reply_src, ip6_current_src_addr(),
|
||||
IP6_NEXTH_ICMP6, q->tot_len);
|
||||
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
|
||||
reply_src, ip6_current_src_addr());
|
||||
|
||||
ICMP6_STATS_INC(icmp6.xmit);
|
||||
ip6_output(q, reply_src, ip6_current_src_addr(), LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
|
||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||
|
||||
@@ -61,17 +61,6 @@
|
||||
#include "lwip/stats.h"
|
||||
|
||||
|
||||
/** Header of the input IPv6 packet currently being processed. */
|
||||
const struct ip6_hdr *current_ip6_header;
|
||||
/** Total header length of current_ip6_header (i.e. after this, the UDP/TCP header starts) */
|
||||
u16_t current_ip6_header_tot_len;
|
||||
/** Source IPv6 address of current_header */
|
||||
ip6_addr_t current_ip6hdr_src;
|
||||
/** Destination IPv6 address of current_header */
|
||||
ip6_addr_t current_ip6hdr_dest;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IPv6 address. It tries to select
|
||||
* a netif following a sequence of heuristics:
|
||||
@@ -380,11 +369,11 @@ ip6_input(struct pbuf *p, struct netif *inp)
|
||||
pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr));
|
||||
|
||||
/* copy IP addresses to aligned ip6_addr_t */
|
||||
ip6_addr_copy(current_ip6hdr_dest, ip6hdr->dest);
|
||||
ip6_addr_copy(current_ip6hdr_src, ip6hdr->src);
|
||||
ip6_addr_copy(ip_data.current_iphdr_dest.ip6, ip6hdr->dest);
|
||||
ip6_addr_copy(ip_data.current_iphdr_src.ip6, ip6hdr->src);
|
||||
|
||||
/* current header pointer. */
|
||||
current_ip6_header = ip6hdr;
|
||||
ip_data.current_ip6_header = ip6hdr;
|
||||
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||
@@ -468,13 +457,13 @@ netif_found:
|
||||
}
|
||||
|
||||
/* current netif pointer. */
|
||||
current_netif = inp;
|
||||
ip_data.current_netif = inp;
|
||||
|
||||
/* Save next header type. */
|
||||
nexth = IP6H_NEXTH(ip6hdr);
|
||||
|
||||
/* Init header length. */
|
||||
hlen = current_ip6_header_tot_len = IP6_HLEN;
|
||||
hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
|
||||
|
||||
/* Move to payload. */
|
||||
pbuf_header(p, -IP6_HLEN);
|
||||
@@ -490,7 +479,7 @@ netif_found:
|
||||
|
||||
/* Get the header length. */
|
||||
hlen = 8 * (1 + *((u8_t *)p->payload) + 1);
|
||||
current_ip6_header_tot_len += hlen;
|
||||
ip_data.current_ip_header_tot_len += hlen;
|
||||
|
||||
/* Skip over this header. */
|
||||
if (hlen > p->len) {
|
||||
@@ -513,7 +502,7 @@ netif_found:
|
||||
|
||||
/* Get the header length. */
|
||||
hlen = 8 * (1 + *((u8_t *)p->payload) + 1);
|
||||
current_ip6_header_tot_len += hlen;
|
||||
ip_data.current_ip_header_tot_len += hlen;
|
||||
|
||||
/* Skip over this header. */
|
||||
if (hlen > p->len) {
|
||||
@@ -536,7 +525,7 @@ netif_found:
|
||||
|
||||
/* Get the header length. */
|
||||
hlen = 8 * (1 + *((u8_t *)p->payload) + 1);
|
||||
current_ip6_header_tot_len += hlen;
|
||||
ip_data.current_ip_header_tot_len += hlen;
|
||||
|
||||
/* Skip over this header. */
|
||||
if (hlen > p->len) {
|
||||
@@ -565,7 +554,7 @@ netif_found:
|
||||
|
||||
/* Fragment Header length. */
|
||||
hlen = 8;
|
||||
current_ip6_header_tot_len += hlen;
|
||||
ip_data.current_ip_header_tot_len += hlen;
|
||||
|
||||
/* Make sure this header fits in current pbuf. */
|
||||
if (hlen > p->len) {
|
||||
@@ -601,7 +590,7 @@ netif_found:
|
||||
* Update all our variables and pointers and continue. */
|
||||
ip6hdr = (struct ip6_hdr *)p->payload;
|
||||
nexth = IP6H_NEXTH(ip6hdr);
|
||||
hlen = current_ip6_header_tot_len = IP6_HLEN;
|
||||
hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
|
||||
pbuf_header(p, -IP6_HLEN);
|
||||
|
||||
#else /* LWIP_IPV6_REASS */
|
||||
@@ -623,7 +612,7 @@ netif_found:
|
||||
options_done:
|
||||
|
||||
/* p points to IPv6 header again. */
|
||||
pbuf_header(p, current_ip6_header_tot_len);
|
||||
pbuf_header(p, ip_data.current_ip_header_tot_len);
|
||||
|
||||
/* send to upper layers */
|
||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
|
||||
@@ -645,21 +634,21 @@ options_done:
|
||||
case IP6_NEXTH_UDPLITE:
|
||||
#endif /* LWIP_UDPLITE */
|
||||
/* Point to payload. */
|
||||
pbuf_header(p, -current_ip6_header_tot_len);
|
||||
pbuf_header(p, -ip_data.current_ip_header_tot_len);
|
||||
udp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case IP6_NEXTH_TCP:
|
||||
/* Point to payload. */
|
||||
pbuf_header(p, -current_ip6_header_tot_len);
|
||||
pbuf_header(p, -ip_data.current_ip_header_tot_len);
|
||||
tcp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_ICMP6
|
||||
case IP6_NEXTH_ICMP6:
|
||||
/* Point to payload. */
|
||||
pbuf_header(p, -current_ip6_header_tot_len);
|
||||
pbuf_header(p, -ip_data.current_ip_header_tot_len);
|
||||
icmp6_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_ICMP */
|
||||
@@ -668,7 +657,7 @@ options_done:
|
||||
/* send ICMP parameter problem unless it was a multicast or ICMPv6 */
|
||||
if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
|
||||
(IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
|
||||
icmp6_param_problem(p, ICMP6_PP_HEADER, current_ip6_header_tot_len - hlen);
|
||||
icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen);
|
||||
}
|
||||
#endif /* LWIP_ICMP */
|
||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", IP6H_NEXTH(ip6hdr)));
|
||||
@@ -680,11 +669,11 @@ options_done:
|
||||
}
|
||||
|
||||
ip6_input_cleanup:
|
||||
current_netif = NULL;
|
||||
current_ip6_header = NULL;
|
||||
current_ip6_header_tot_len = 0;
|
||||
ip6_addr_set_any(¤t_ip6hdr_src);
|
||||
ip6_addr_set_any(¤t_ip6hdr_dest);
|
||||
ip_data.current_netif = NULL;
|
||||
ip_data.current_ip6_header = NULL;
|
||||
ip_data.current_ip_header_tot_len = 0;
|
||||
ip6_addr_set_any(&ip_data.current_iphdr_src.ip6);
|
||||
ip6_addr_set_any(&ip_data.current_iphdr_dest.ip6);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -727,7 +716,7 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
LWIP_ASSERT("p->ref == 1", p->ref == 1);
|
||||
|
||||
/* Should the IPv6 header be generated or is it already included in p? */
|
||||
if (dest != IP6_HDRINCL) {
|
||||
if (dest != IP_HDRINCL) {
|
||||
/* generate IPv6 header */
|
||||
if (pbuf_header(p, IP6_HLEN)) {
|
||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
|
||||
@@ -883,9 +872,9 @@ ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
NETIF_SET_HWADDRHINT(netif, addr_hint);
|
||||
err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
|
||||
netif->addr_hint = NULL;
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 Checksum helper functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#ifndef LWIP_CHKSUM
|
||||
# define LWIP_CHKSUM lwip_standard_chksum
|
||||
extern u16_t lwip_standard_chksum(void *dataptr, u16_t len);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/* fold the upper bit down */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
for (swapped = 0; swapped < 4; swapped++) {
|
||||
addr = src->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("ip6_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order. Will only compute for a
|
||||
* portion of the payload.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @param chksum_len number of payload bytes used to compute chksum
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo_partial(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u16_t chklen;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||
chklen = q->len;
|
||||
if (chklen > chksum_len) {
|
||||
chklen = chksum_len;
|
||||
}
|
||||
acc += LWIP_CHKSUM(q->payload, chklen);
|
||||
chksum_len -= chklen;
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
for (swapped = 0; swapped < 4; swapped++) {
|
||||
addr = src->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("ip6_chksum_pseudo_partial(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
@@ -50,7 +50,7 @@
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/memp.h"
|
||||
@@ -560,8 +560,8 @@ mld6_send(struct mld_group *group, u8_t type)
|
||||
mld_hdr->reserved = 0;
|
||||
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
|
||||
|
||||
mld_hdr->chksum = ip6_chksum_pseudo(p, src_addr, &(group->group_address),
|
||||
IP6_NEXTH_ICMP6, p->len);
|
||||
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
|
||||
src_addr, &(group->group_address));
|
||||
|
||||
/* Add hop-by-hop headers options: router alert with MLD value. */
|
||||
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/mld6.h"
|
||||
@@ -827,8 +827,8 @@ nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags)
|
||||
target_addr = &multicast_address;
|
||||
}
|
||||
|
||||
ns_hdr->chksum = ip6_chksum_pseudo(p, src_addr, target_addr,
|
||||
IP6_NEXTH_ICMP6, p->len);
|
||||
ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
|
||||
target_addr);
|
||||
|
||||
/* Send the packet out. */
|
||||
ND6_STATS_INC(nd6.xmit);
|
||||
@@ -897,8 +897,8 @@ nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags)
|
||||
dest_addr = ip6_current_src_addr();
|
||||
}
|
||||
|
||||
na_hdr->chksum = ip6_chksum_pseudo(p, src_addr, dest_addr,
|
||||
IP6_NEXTH_ICMP6, p->len);
|
||||
na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
|
||||
dest_addr);
|
||||
|
||||
/* Send the packet out. */
|
||||
ND6_STATS_INC(nd6.xmit);
|
||||
@@ -964,8 +964,8 @@ nd6_send_rs(struct netif * netif)
|
||||
SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
|
||||
}
|
||||
|
||||
rs_hdr->chksum = ip6_chksum_pseudo(p, src_addr, &multicast_address,
|
||||
IP6_NEXTH_ICMP6, p->len);
|
||||
rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
|
||||
&multicast_address);
|
||||
|
||||
/* Send the packet out. */
|
||||
ND6_STATS_INC(nd6.xmit);
|
||||
@@ -1407,12 +1407,11 @@ nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif)
|
||||
s8_t i;
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
/* TODO should addr_hint point to nd6_cached_neighbor_index instead? */
|
||||
if (netif->addr_hint != NULL) {
|
||||
/* per-pcb cached entry was given */
|
||||
i = *(netif->addr_hint);
|
||||
if ((i >= 0) && (i < LWIP_ND6_NUM_DESTINATIONS)) {
|
||||
nd6_cached_destination_index = i;
|
||||
u8_t addr_hint = *(netif->addr_hint);
|
||||
if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) {
|
||||
nd6_cached_destination_index = addr_hint;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
@@ -1425,7 +1424,7 @@ nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif)
|
||||
} else {
|
||||
/* Search destination cache. */
|
||||
i = nd6_find_destination_cache_entry(ip6addr);
|
||||
if (i>= 0) {
|
||||
if (i >= 0) {
|
||||
/* found destination entry. make it our new cached index. */
|
||||
nd6_cached_destination_index = i;
|
||||
}
|
||||
@@ -1465,7 +1464,6 @@ nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif)
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
/* TODO should addr_hint point to nd6_cached_neighbor_index instead? */
|
||||
if (netif->addr_hint != NULL) {
|
||||
/* per-pcb cached entry was given */
|
||||
*(netif->addr_hint) = nd6_cached_destination_index;
|
||||
|
||||
@@ -202,9 +202,7 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
netif->state = state;
|
||||
netif->num = netifnum++;
|
||||
netif->input = input;
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
|
||||
netif->loop_cnt_current = 0;
|
||||
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
|
||||
@@ -365,10 +363,10 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip.ip4), &(netif->ip_addr))
|
||||
if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr))
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||
&& !ip_addr_islinklocal(&(pcb->local_ip.ip4))
|
||||
&& !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
) {
|
||||
/* this connection must be aborted */
|
||||
@@ -382,11 +380,11 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
}
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if ((!(ip_addr_isany(&(lpcb->local_ip.ip4)))) &&
|
||||
(ip_addr_cmp(&(lpcb->local_ip.ip4), &(netif->ip_addr)))) {
|
||||
if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) &&
|
||||
(ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_set(&(lpcb->local_ip.ip4), ipaddr);
|
||||
ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,21 +190,21 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
switch (layer) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset += PBUF_TRANSPORT_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||
break;
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset += PBUF_IP_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||
break;
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset += PBUF_LINK_HLEN;
|
||||
offset = PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
offset = 0;
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
||||
@@ -348,21 +348,21 @@ pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_cust
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
switch (l) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset += PBUF_TRANSPORT_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||
break;
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset += PBUF_IP_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||
break;
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset += PBUF_LINK_HLEN;
|
||||
offset = PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
offset = 0;
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
|
||||
|
||||
168
src/core/raw.c
168
src/core/raw.c
@@ -105,17 +105,9 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
/* loop through all raw pcbs until the packet is eaten by one */
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if ((pcb->protocol == proto) &&
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_addr_isany(&pcb->local_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&pcb->local_ip.ip4) ||
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr()))))) {
|
||||
if ((pcb->protocol == proto) && IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||
(ipX_addr_isany(pcb->isipv6, &pcb->local_ip) ||
|
||||
ipX_addr_cmp(pcb->isipv6, &(pcb->local_ip), ipX_current_dest_addr()))) {
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
/* broadcast filter? */
|
||||
if (((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp))
|
||||
@@ -128,15 +120,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv.ip4 != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
eaten = pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr());
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||
}
|
||||
eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||
if (eaten != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
@@ -177,15 +161,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
err_t
|
||||
raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip.ip4, ipaddr);
|
||||
}
|
||||
ipX_addr_set_ipaddr(pcb->isipv6, &pcb->local_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -205,15 +181,7 @@ raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
err_t
|
||||
raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip.ip4, ipaddr);
|
||||
}
|
||||
ipX_addr_set_ipaddr(pcb->isipv6, &pcb->remote_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -258,38 +226,22 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
struct netif *netif;
|
||||
ip_addr_t *src_ip;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||
|
||||
s16_t header_size;
|
||||
#if LWIP_IPV6
|
||||
/* TODO lots of v4 and v6 code duplication, optimize! Or will compiler optimize? */
|
||||
if (pcb->isipv6) {
|
||||
/* not enough space to add an IPv6 header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP6_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 | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: 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_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
if(pbuf_header(q, -IP6_HLEN)) {
|
||||
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ip6_addr_t *ip6addr = ip_2_ip6(ipaddr);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||
|
||||
header_size = (
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 ? IP6_HLEN :
|
||||
#endif /* LWIP_IPV6 */
|
||||
IP_HLEN);
|
||||
|
||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
if (pbuf_header(p, header_size)) {
|
||||
/* allocate header in new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
@@ -306,7 +258,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
if(pbuf_header(q, -IP_HLEN)) {
|
||||
if(pbuf_header(q, -header_size)) {
|
||||
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
||||
return ERR_MEM;
|
||||
}
|
||||
@@ -314,20 +266,14 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if ((netif = ip6_route(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to IPv6 destionation\n"));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
netif = ip6_route(ipX_2_ip6(&pcb->local_ip), ip6addr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
||||
netif = ip_route(ipaddr);
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
|
||||
ipX_addr_debug_print(pcb->isipv6, RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ip_2_ipX(ipaddr));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
@@ -337,8 +283,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
#if LWIP_IPV6
|
||||
if (!netif->isipv6) {
|
||||
/* @todo: why does IPv6 not filter broadcast with SOF_BROADCAST enabled? */
|
||||
if (!netif->isipv6)
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
/* broadcast filter? */
|
||||
if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
@@ -348,54 +296,48 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
|
||||
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&pcb->local_ip.ip6)) {
|
||||
ip6_addr_t *src6_ip;
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
/* select an IPv6 address from the netif as source address */
|
||||
src_ip = (ip_addr_t *)ip6_select_source_address(netif, (ip6_addr_t *)ipaddr);
|
||||
if (src_ip == NULL) {
|
||||
src6_ip = ip6_select_source_address(netif, ip6addr);
|
||||
if (src6_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
err = ERR_RTE;
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
/* did we chain a header earlier? */
|
||||
if (q != p) {
|
||||
/* free the header */
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
} else {
|
||||
/* use RAW PCB local IPv6 address as source address */
|
||||
src_ip = (ip_addr_t *)&(pcb->local_ip.ip6);
|
||||
src6_ip = ipX_2_ip6(&pcb->local_ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4)) {
|
||||
/* 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.ip4);
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t *)src_ip, (ip6_addr_t *)ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
err = ip6_output_if(q, src6_ip, ip6addr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
if (ip_addr_isany(ipX_2_ip(&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 = ipX_2_ip(&pcb->local_ip);
|
||||
}
|
||||
err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
/* did we chain a header earlier? */
|
||||
if (q != p) {
|
||||
/* free the header */
|
||||
@@ -414,13 +356,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
err_t
|
||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* TODO is this necessary, or ar ip4 and ip6 pointers the same (think union)? */
|
||||
return raw_sendto(pcb, p, (ip_addr_t *)&pcb->remote_ip.ip6);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
return raw_sendto(pcb, p, &pcb->remote_ip.ip4);
|
||||
return raw_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,9 +435,7 @@ raw_new_ip6(u8_t proto)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
pcb = raw_new(proto);
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
ip_set_v6(pcb, 1);
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
@@ -1797,7 +1797,7 @@ void snmp_insert_udpidx_tree(struct udp_pcb *pcb)
|
||||
u8_t level;
|
||||
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
snmp_iptooid(&pcb->local_ip, &udpidx[0]);
|
||||
snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]);
|
||||
udpidx[4] = pcb->local_port;
|
||||
|
||||
udp_rn = &udp_root;
|
||||
@@ -1850,7 +1850,7 @@ void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
|
||||
u8_t bindings, fc, level, del_cnt;
|
||||
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
snmp_iptooid(&pcb->local_ip, &udpidx[0]);
|
||||
snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]);
|
||||
udpidx[4] = pcb->local_port;
|
||||
|
||||
/* count PCBs for a given binding
|
||||
@@ -1859,7 +1859,7 @@ void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
|
||||
npcb = udp_pcbs;
|
||||
while ((npcb != NULL))
|
||||
{
|
||||
if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) &&
|
||||
if (ipX_addr_cmp(0, &npcb->local_ip, &pcb->local_ip) &&
|
||||
(npcb->local_port == udpidx[4]))
|
||||
{
|
||||
bindings++;
|
||||
@@ -3881,17 +3881,17 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
u8_t id;
|
||||
struct udp_pcb *pcb;
|
||||
ip_addr_t ip;
|
||||
ipX_addr_t ip;
|
||||
u16_t port;
|
||||
|
||||
LWIP_UNUSED_ARG(len);
|
||||
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
|
||||
snmp_oidtoip(&od->id_inst_ptr[1], (ip_addr_t*)&ip);
|
||||
LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff));
|
||||
port = (u16_t)od->id_inst_ptr[5];
|
||||
|
||||
pcb = udp_pcbs;
|
||||
while ((pcb != NULL) &&
|
||||
!(ip_addr_cmp(&pcb->local_ip, &ip) &&
|
||||
!(ipX_addr_cmp(0, &pcb->local_ip, &ip) &&
|
||||
(pcb->local_port == port)))
|
||||
{
|
||||
pcb = pcb->next;
|
||||
@@ -3905,8 +3905,8 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
case 1: /* udpLocalAddress */
|
||||
{
|
||||
ip_addr_t *dst = (ip_addr_t*)value;
|
||||
*dst = pcb->local_ip;
|
||||
ipX_addr_t *dst = (ipX_addr_t*)value;
|
||||
ipX_addr_copy(0, *dst, pcb->local_ip);
|
||||
}
|
||||
break;
|
||||
case 2: /* udpLocalPort */
|
||||
|
||||
254
src/core/tcp.c
254
src/core/tcp.c
@@ -150,17 +150,8 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
||||
|
||||
/* don't call tcp_abort here: we must not deallocate the pcb since
|
||||
that might not be expected when calling tcp_close */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port, pcb->isipv6);
|
||||
|
||||
tcp_pcb_purge(pcb);
|
||||
|
||||
@@ -330,8 +321,6 @@ void
|
||||
tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
{
|
||||
u32_t seqno, ackno;
|
||||
/*u16_t remote_port, local_port;
|
||||
ip_addr_t remote_ip, local_ip; */
|
||||
#if LWIP_CALLBACK_API
|
||||
tcp_err_fn errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
@@ -349,10 +338,6 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
} else {
|
||||
seqno = pcb->snd_nxt;
|
||||
ackno = pcb->rcv_nxt;
|
||||
/*ip_addr_copy(local_ip, pcb->local_ip.ip4);
|
||||
ip_addr_copy(remote_ip, pcb->remote_ip.ip4);
|
||||
local_port = pcb->local_port;
|
||||
remote_port = pcb->remote_port;*/
|
||||
#if LWIP_CALLBACK_API
|
||||
errf = pcb->errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
@@ -371,15 +356,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
if (reset) {
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(seqno, ackno, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(seqno, ackno, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port, pcb->isipv6);
|
||||
}
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
||||
@@ -452,40 +429,20 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
((cpcb->so_options & SOF_REUSEADDR) == 0))
|
||||
#endif /* SO_REUSE */
|
||||
{
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
!pcb->isipv6 &&
|
||||
!cpcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&(cpcb->local_ip.ip4)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(cpcb->local_ip.ip4), ipaddr))) {
|
||||
/* @todo: check accept_any_ip_version */
|
||||
if (IP_PCB_IPVER_EQ(pcb, cpcb) &&
|
||||
(ipX_addr_isany(PCB_ISIPV6(pcb), &cpcb->local_ip) ||
|
||||
ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr)) ||
|
||||
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, ip_2_ipX(ipaddr)))) {
|
||||
return ERR_USE;
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6 &&
|
||||
cpcb->isipv6 &&
|
||||
(ip6_addr_isany(&(cpcb->local_ip.ip6)) ||
|
||||
ip6_addr_isany((ip6_addr_t *)ipaddr) ||
|
||||
ip6_addr_cmp(&(cpcb->local_ip.ip6), (ip6_addr_t *)ipaddr))) {
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (!ip6_addr_isany((ip6_addr_t *)ipaddr)) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (!ip_addr_isany(ipaddr)) {
|
||||
pcb->local_ip.ip4 = *ipaddr;
|
||||
if (!ipX_addr_isany(pcb->isipv6, ip_2_ipX(ipaddr))) {
|
||||
ipX_addr_set(pcb->isipv6, &pcb->local_ip, ip_2_ipX(ipaddr));
|
||||
}
|
||||
pcb->local_port = port;
|
||||
TCP_REG(&tcp_bound_pcbs, pcb);
|
||||
@@ -539,16 +496,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
is declared (listen-/connection-pcb), we have to make sure now that
|
||||
this port is only used once for every local IP. */
|
||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if (lpcb->local_port == pcb->local_port) {
|
||||
if ((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
lpcb->isipv6 &&
|
||||
ip6_addr_cmp(&lpcb->local_ip.ip6, &pcb->local_ip.ip6)) ||
|
||||
(!pcb->isipv6 &&
|
||||
!lpcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&lpcb->local_ip.ip4, &pcb->local_ip.ip4))) {
|
||||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
IP_PCB_IPVER_EQ(pcb, lpcb)) {
|
||||
if (ipX_addr_cmp(pcb->isipv6, &lpcb->local_ip, &pcb->local_ip)) {
|
||||
/* this address/port is already used */
|
||||
return NULL;
|
||||
}
|
||||
@@ -570,14 +520,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
lpcb->tos = pcb->tos;
|
||||
#if LWIP_IPV6
|
||||
lpcb->isipv6 = pcb->isipv6;
|
||||
if (lpcb->isipv6) {
|
||||
ip6_addr_copy(lpcb->local_ip.ip6, pcb->local_ip.ip6);
|
||||
}
|
||||
else
|
||||
lpcb->accept_any_ip_version = 0;
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_copy(lpcb->local_ip.ip4, pcb->local_ip.ip4);
|
||||
}
|
||||
ipX_addr_copy(pcb->isipv6, lpcb->local_ip, pcb->local_ip);
|
||||
if (pcb->local_port != 0) {
|
||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||
}
|
||||
@@ -593,7 +538,28 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
return (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
|
||||
/**
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Same as tcp_listen_with_backlog, but allows to accept IPv4 and IPv6
|
||||
* connections, if the pcb's local address is set to ANY.
|
||||
*/
|
||||
struct tcp_pcb *
|
||||
tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
{
|
||||
struct tcp_pcb *lpcb;
|
||||
|
||||
if (!ipX_addr_isany(pcb->isipv6, &pcb->local_ip)) {
|
||||
return NULL;
|
||||
}
|
||||
lpcb = tcp_listen_with_backlog(pcb, backlog);
|
||||
if (lpcb != NULL) {
|
||||
((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1;
|
||||
}
|
||||
return lpcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Update the state that tracks the available window space to advertise.
|
||||
*
|
||||
* Returns how much extra window would be advertised if we sent an
|
||||
@@ -716,15 +682,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
||||
if (ipaddr != NULL) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->remote_ip.ip4 = *ipaddr;
|
||||
}
|
||||
ipX_addr_set(PCB_ISIPV6(pcb), &pcb->remote_ip, ip_2_ipX(ipaddr));
|
||||
} else {
|
||||
return ERR_VAL;
|
||||
}
|
||||
@@ -733,38 +691,38 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
/* check if we have a route to the remote host */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&(pcb->local_ip.ip6))) {
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
/* no local IPv6 address set, yet. */
|
||||
ip6_addr_t * local_addr6;
|
||||
struct netif *netif = ip6_route(&(pcb->remote_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
struct netif *netif = ip6_route(ipX_2_ip6(&pcb->remote_ip), ipX_2_ip6(&pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no route
|
||||
since that will fail. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* Select and IPv6 address from the netif. */
|
||||
local_addr6 = ip6_select_source_address(netif, &(pcb->remote_ip.ip6));
|
||||
local_addr6 = ip6_select_source_address(netif, ipX_2_ip6(&pcb->remote_ip));
|
||||
if (local_addr6 == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no suitable
|
||||
source address. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
ip6_addr_set(&pcb->local_ip.ip6, local_addr6);
|
||||
ip6_addr_set(ipX_2_ip6(&pcb->local_ip), local_addr6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&(pcb->local_ip.ip4))) {
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||
/* no local IP address set, yet. */
|
||||
struct netif *netif = ip_route(&(pcb->remote_ip.ip4));
|
||||
struct netif *netif = ip_route(ipX_2_ip(&pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no route
|
||||
since that will fail. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* Use the netif's IP address as local address. */
|
||||
ip_addr_copy(pcb->local_ip.ip4, netif->ip_addr);
|
||||
ip_addr_copy(*ipX_2_ip(&pcb->local_ip), netif->ip_addr);
|
||||
}
|
||||
|
||||
old_local_port = pcb->local_port;
|
||||
@@ -782,18 +740,9 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
||||
if ((cpcb->local_port == pcb->local_port) &&
|
||||
(cpcb->remote_port == port) &&
|
||||
#if LWIP_IPV6
|
||||
((cpcb->isipv6 &&
|
||||
pcb->isipv6 &&
|
||||
ip6_addr_cmp(&cpcb->local_ip.ip6, &pcb->local_ip.ip6) &&
|
||||
ip6_addr_cmp(&cpcb->remote_ip.ip6, (ip6_addr_t *)ipaddr)) ||
|
||||
(!cpcb->isipv6 &&
|
||||
!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&cpcb->local_ip.ip4, &pcb->local_ip.ip4) &&
|
||||
ip_addr_cmp(&cpcb->remote_ip.ip4, ipaddr)))) {
|
||||
IP_PCB_IPVER_EQ(cpcb, pcb) &&
|
||||
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, &pcb->local_ip) &&
|
||||
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->remote_ip, ip_2_ipX(ipaddr))) {
|
||||
/* linux returns EISCONN here, but ERR_USE should be OK for us */
|
||||
return ERR_USE;
|
||||
}
|
||||
@@ -814,15 +763,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
The send MSS is updated when an MSS option is received. */
|
||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
pcb->mss = tcp_eff_send_mss_ip6(pcb->mss, &pcb->local_ip.ip6, &pcb->remote_ip.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->remote_ip.ip4);
|
||||
}
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, pcb->isipv6);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
pcb->cwnd = 1;
|
||||
pcb->ssthresh = pcb->mss * 10;
|
||||
@@ -962,11 +903,7 @@ tcp_slowtmr(void)
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
{
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, TCP_DEBUG, &pcb->remote_ip);
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
++pcb_remove;
|
||||
@@ -1032,17 +969,8 @@ tcp_slowtmr(void)
|
||||
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
|
||||
if (pcb_reset) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port, pcb->isipv6);
|
||||
}
|
||||
|
||||
pcb2 = pcb;
|
||||
@@ -1401,10 +1329,7 @@ tcp_new_ip6(void)
|
||||
{
|
||||
struct tcp_pcb * pcb;
|
||||
pcb = tcp_alloc(TCP_PRIO_NORMAL);
|
||||
/* could allocate TCP PCB? */
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
ip_set_v6(pcb, 1);
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
@@ -1519,18 +1444,9 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
tcp_listen_pcbs.listen_pcbs != NULL);
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
#if LWIP_IPV6
|
||||
((lpcb->isipv6 &&
|
||||
pcb->isipv6 &&
|
||||
(ip6_addr_isany(&lpcb->local_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, &lpcb->local_ip.ip6))) ||
|
||||
(!lpcb->isipv6 &&
|
||||
!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&lpcb->local_ip.ip4) ||
|
||||
ip_addr_cmp(&pcb->local_ip.ip4, &lpcb->local_ip.ip4))))) {
|
||||
IP_PCB_IPVER_EQ(pcb, lpcb) &&
|
||||
(ipX_addr_isany(lpcb->isipv6, &lpcb->local_ip) ||
|
||||
ipX_addr_cmp(lpcb->isipv6, &pcb->local_ip, &lpcb->local_ip))) {
|
||||
/* port and address of the listen pcb match the timed-out pcb */
|
||||
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
||||
lpcb->accepts_pending > 0);
|
||||
@@ -1629,14 +1545,35 @@ tcp_next_iss(void)
|
||||
* calculating the minimum of TCP_MSS and that netif's mtu (if set).
|
||||
*/
|
||||
u16_t
|
||||
tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
|
||||
tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
|
||||
#if LWIP_IPV6
|
||||
, ipX_addr_t *src, u8_t isipv6
|
||||
#endif /* LWIP_IPV6 */
|
||||
)
|
||||
{
|
||||
u16_t mss_s;
|
||||
struct netif *outif;
|
||||
s16_t mtu;
|
||||
s16_t iphlen = IP_HLEN;
|
||||
|
||||
outif = ip_route(addr);
|
||||
if ((outif != NULL) && (outif->mtu != 0)) {
|
||||
mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
|
||||
#if LWIP_IPV6
|
||||
if (isipv6) {
|
||||
/* First look in destination cache, to see if there is a Path MTU. */
|
||||
outif = ip6_route(ipX_2_ip6(src), ipX_2_ip6(dest));
|
||||
mtu = nd6_get_destination_mtu(ipX_2_ip6(dest), outif);
|
||||
iphlen = IP6_HLEN;
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
outif = ip_route(ipX_2_ip(dest));
|
||||
if (outif == NULL) {
|
||||
return sendmss;
|
||||
}
|
||||
mtu = outif->mtu;
|
||||
}
|
||||
|
||||
if (mtu != 0) {
|
||||
mss_s = mtu - iphlen - TCP_HLEN;
|
||||
/* RFC 1122, chap 4.2.2.6:
|
||||
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
||||
* We correct for TCP options in tcp_write(), and don't support IP options.
|
||||
@@ -1645,35 +1582,6 @@ tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
|
||||
}
|
||||
return sendmss;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Calculates the effective send mss that can be used for a specific IPv6
|
||||
* address by using ip6_route to determine the netif used to send to the
|
||||
* address and calculating the minimum of TCP_MSS and that netif's mtu (if set).
|
||||
*/
|
||||
u16_t
|
||||
tcp_eff_send_mss_ip6(u16_t sendmss, ip6_addr_t *src, ip6_addr_t *dest)
|
||||
{
|
||||
u16_t mss_s;
|
||||
struct netif *outif;
|
||||
s16_t mtu;
|
||||
|
||||
/* First look in destination cache, to see if there is a PAth MTU. */
|
||||
outif = ip6_route(src, dest);
|
||||
mtu = nd6_get_destination_mtu(dest, outif);
|
||||
|
||||
if (mtu != 0) {
|
||||
mss_s = mtu - IP6_HLEN - TCP_HLEN;
|
||||
/* RFC 1122, chap 4.2.2.6:
|
||||
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
||||
* We correct for TCP options in tcp_write().
|
||||
*/
|
||||
sendmss = LWIP_MIN(sendmss, mss_s);
|
||||
}
|
||||
return sendmss;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
const char*
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
#include "lwip/nd6.h"
|
||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||
@@ -104,6 +104,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
#endif /* SO_REUSE */
|
||||
u8_t hdrlen;
|
||||
err_t err;
|
||||
u16_t chksum;
|
||||
|
||||
PERF_START;
|
||||
|
||||
@@ -121,62 +122,26 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||
TCP_STATS_INC(tcp.lenerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
/* Don't even process incoming broadcasts/multicasts. */
|
||||
if ((
|
||||
#if LWIP_IPV6
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_ismulticast(ip6_current_dest_addr())) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isbroadcast(ip_current_dest_addr(), inp) ||
|
||||
ip_addr_ismulticast(ip_current_dest_addr())))) {
|
||||
if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) ||
|
||||
ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) {
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
#if CHECKSUM_CHECK_TCP
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_TCP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||
ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_TCP, p->tot_len)));
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print(tcphdr);
|
||||
#endif /* TCP_DEBUG */
|
||||
TCP_STATS_INC(tcp.chkerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* Verify TCP checksum. */
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_TCP, p->tot_len) != 0) {
|
||||
chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len,
|
||||
ipX_current_src_addr(), ipX_current_dest_addr());
|
||||
if (chksum != 0) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||
inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_TCP, p->tot_len)));
|
||||
#if TCP_DEBUG
|
||||
chksum));
|
||||
tcp_debug_print(tcphdr);
|
||||
#endif /* TCP_DEBUG */
|
||||
TCP_STATS_INC(tcp.chkerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
#endif /* CHECKSUM_CHECK_TCP */
|
||||
|
||||
@@ -187,10 +152,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
|
||||
TCP_STATS_INC(tcp.lenerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
/* Convert fields in TCP header to host byte order. */
|
||||
@@ -214,18 +176,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_cmp(&(pcb->remote_ip.ip6), ip6_current_src_addr()) &&
|
||||
ip6_addr_cmp(&(pcb->local_ip.ip6), ip6_current_dest_addr())) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr()) &&
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr())))) {
|
||||
|
||||
IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||
ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
|
||||
ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
|
||||
/* Move this PCB to the front of the list so that subsequent
|
||||
lookups will be faster (we exploit locality in TCP segment
|
||||
arrivals). */
|
||||
@@ -248,17 +201,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_cmp(&(pcb->remote_ip.ip6), ip6_current_src_addr()) &&
|
||||
ip6_addr_cmp(&(pcb->local_ip.ip6), ip6_current_dest_addr())) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr()) &&
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr())))) {
|
||||
IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||
ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
|
||||
ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
|
||||
/* We don't really care enough to move this PCB to the front
|
||||
of the list since we are not very likely to receive that
|
||||
many segments for connections in TIME-WAIT. */
|
||||
@@ -274,53 +219,31 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
prev = NULL;
|
||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if (lpcb->local_port == tcphdr->dest) {
|
||||
#if LWIP_IPV6
|
||||
if (lpcb->accept_any_ip_version) {
|
||||
/* found an ANY-match */
|
||||
#if SO_REUSE
|
||||
#if LWIP_IPV6
|
||||
if (lpcb->isipv6 &&
|
||||
(ip6_current_header() != NULL)) {
|
||||
if (ip6_addr_cmp(&(lpcb->local_ip.ip6), ip6_current_dest_addr())) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip6_addr_isany(&(lpcb->local_ip.ip6))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
}
|
||||
}
|
||||
else if (!lpcb->isipv6 &&
|
||||
(ip_current_header() != NULL))
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
if (ip_addr_cmp(&(lpcb->local_ip.ip4), ip_current_dest_addr())) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip_addr_isany(&(lpcb->local_ip.ip4))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
}
|
||||
}
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
#else /* SO_REUSE */
|
||||
#if LWIP_IPV6
|
||||
if (lpcb->isipv6 &&
|
||||
(ip6_current_header() != NULL)) {
|
||||
if (ip6_addr_cmp(&(lpcb->local_ip.ip6), ip6_current_dest_addr()) ||
|
||||
ip6_addr_isany(&(lpcb->local_ip.ip6))) {
|
||||
break;
|
||||
#endif /* SO_REUSE */
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) {
|
||||
if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!lpcb->isipv6 &&
|
||||
(ip_current_header() != NULL))
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
if (ip_addr_cmp(&(lpcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
ip_addr_isany(&(lpcb->local_ip.ip4))) {
|
||||
/* found a match */
|
||||
} else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) {
|
||||
/* found an ANY-match */
|
||||
#if SO_REUSE
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
#else /* SO_REUSE */
|
||||
break;
|
||||
#endif /* SO_REUSE */
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
}
|
||||
prev = (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
@@ -387,10 +310,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* Drop incoming packets because pcb is "full" (only if the incoming
|
||||
segment contains data). */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
}
|
||||
tcp_input_pcb = pcb;
|
||||
@@ -493,25 +413,19 @@ aborted:
|
||||
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen,
|
||||
ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
||||
PERF_STOP("tcp_input");
|
||||
return;
|
||||
dropped:
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,19 +452,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
/* For incoming segments with the ACK flag set, respond with a
|
||||
RST. */
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno + 1, seqno + tcplen,
|
||||
ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno + 1, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
tcp_rst(ackno + 1, seqno + tcplen, ipX_current_dest_addr(),
|
||||
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||
} else if (flags & TCP_SYN) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
@@ -573,17 +476,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
/* Set up the new PCB. */
|
||||
#if LWIP_IPV6
|
||||
npcb->isipv6 = pcb->isipv6;
|
||||
if (npcb->isipv6) {
|
||||
ip6_addr_copy(npcb->local_ip.ip6, *ip6_current_dest_addr());
|
||||
ip6_addr_copy(npcb->remote_ip.ip6, *ip6_current_src_addr());
|
||||
}
|
||||
else
|
||||
npcb->isipv6 = ip_current_is_v6();
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_copy(npcb->local_ip.ip4, *ip_current_dest_addr());
|
||||
ip_addr_copy(npcb->remote_ip.ip4, *ip_current_src_addr());
|
||||
}
|
||||
ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr());
|
||||
ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr());
|
||||
npcb->local_port = pcb->local_port;
|
||||
npcb->remote_port = tcphdr->src;
|
||||
npcb->state = SYN_RCVD;
|
||||
@@ -605,15 +501,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
/* Parse any options in the SYN. */
|
||||
tcp_parseopt(npcb);
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
#if LWIP_IPV6
|
||||
if (npcb->isipv6) {
|
||||
npcb->mss = tcp_eff_send_mss_ip6(npcb->mss, &(npcb->local_ip.ip6), &(npcb->remote_ip.ip6));
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip.ip4));
|
||||
}
|
||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip,
|
||||
&npcb->remote_ip, npcb->isipv6);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
snmp_inc_tcppassiveopens();
|
||||
@@ -655,17 +544,8 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
||||
should be sent in reply */
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||
/* If the SYN is in the window it is an error, send a reset */
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||
return ERR_OK;
|
||||
}
|
||||
} else if (flags & TCP_FIN) {
|
||||
@@ -762,15 +642,8 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->state = ESTABLISHED;
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
pcb->mss = tcp_eff_send_mss_ip6(pcb->mss, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip.ip4));
|
||||
}
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->isipv6);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
/* Set ssthresh again after changing pcb->mss (already set in tcp_connect
|
||||
@@ -806,17 +679,8 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
/* received ACK? possibly a half-open connection */
|
||||
else if (flags & TCP_ACK) {
|
||||
/* send a RST to bring the other side in a non-synchronized state. */
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||
}
|
||||
break;
|
||||
case SYN_RCVD:
|
||||
@@ -858,17 +722,8 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
}
|
||||
} else {
|
||||
/* incorrect ACK number, send RST */
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||
}
|
||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||
/* Looks like another copy of the SYN - retransmit our SYN-ACK */
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -868,34 +868,17 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* Chksum is mandatory over IPv6 */
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip6_output_hinted(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip6_output(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = ipX_chksum_pseudo(pcb->isipv6, p, IP_PROTO_TCP, p->tot_len,
|
||||
&pcb->local_ip, &pcb->remote_ip);
|
||||
#endif
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
ipX_output_hinted(pcb->isipv6, p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &pcb->addr_hint);
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
ipX_output(pcb->isipv6, p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
@@ -1108,28 +1091,28 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
calling ip_route(). */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&(pcb->local_ip.ip6))) {
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
ip6_addr_t * local_addr6;
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
netif = ip6_route(ipX_2_ip6(&pcb->local_ip), ipX_2_ip6(&pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
/* Select and IPv6 address from the netif. */
|
||||
local_addr6 = ip6_select_source_address(netif, &(pcb->remote_ip.ip6));
|
||||
local_addr6 = ip6_select_source_address(netif, ipX_2_ip6(&pcb->remote_ip));
|
||||
if (local_addr6 == NULL) {
|
||||
return;
|
||||
}
|
||||
ip6_addr_set(&pcb->local_ip.ip6, local_addr6);
|
||||
ip6_addr_set(ipX_2_ip6(&pcb->local_ip), local_addr6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&(pcb->local_ip.ip4))) {
|
||||
netif = ip_route(&(pcb->remote_ip.ip4));
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||
netif = ip_route(ipX_2_ip(&pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
ip_addr_copy(pcb->local_ip.ip4, netif->ip_addr);
|
||||
ip_addr_copy(*ipX_2_ip(&pcb->local_ip), netif->ip_addr);
|
||||
}
|
||||
|
||||
if (pcb->rttest == 0) {
|
||||
@@ -1154,20 +1137,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
{
|
||||
u32_t acc;
|
||||
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
|
||||
u16_t chksum_slow;
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
chksum_slow = ip6_chksum_pseudo(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
}
|
||||
u16_t chksum_slow = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
|
||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||
if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
|
||||
LWIP_ASSERT("data included but not checksummed",
|
||||
@@ -1175,19 +1146,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
}
|
||||
|
||||
/* rebuild TCP header checksum (TCP header changes for retransmissions!) */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
acc = ip6_chksum_pseudo_partial(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
||||
}
|
||||
acc = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||
seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
|
||||
/* add payload checksum */
|
||||
if (seg->chksum_swapped) {
|
||||
seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
|
||||
@@ -1205,46 +1165,21 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||
}
|
||||
#else /* TCP_CHECKSUM_ON_COPY */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* Chksum is mandatory in IPv6 */
|
||||
seg->tcphdr->chksum = ip6_chksum_pseudo(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
seg->tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
|
||||
#endif /* CHECKSUM_GEN_TCP */
|
||||
}
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip6_output_hinted(seg->p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP, &(pcb->addr_hint));
|
||||
ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip6_output(seg->p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP);
|
||||
ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||
pcb->tos, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(seg->p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(seg->p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1268,9 +1203,13 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
* @param remote_port the remote TCP port to send the segment to
|
||||
*/
|
||||
void
|
||||
tcp_rst(u32_t seqno, u32_t ackno,
|
||||
ip_addr_t *local_ip, ip_addr_t *remote_ip,
|
||||
u16_t local_port, u16_t remote_port)
|
||||
tcp_rst_impl(u32_t seqno, u32_t ackno,
|
||||
ipX_addr_t *local_ip, ipX_addr_t *remote_ip,
|
||||
u16_t local_port, u16_t remote_port
|
||||
#if LWIP_IPV6
|
||||
, u8_t isipv6
|
||||
#endif /* LWIP_IPV6 */
|
||||
)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
@@ -1292,77 +1231,19 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
||||
tcphdr->chksum = 0;
|
||||
tcphdr->urgp = 0;
|
||||
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
snmp_inc_tcpoutrsts();
|
||||
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = ipX_chksum_pseudo(isipv6, p, IP_PROTO_TCP, p->tot_len,
|
||||
local_ip, remote_ip);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
snmp_inc_tcpoutrsts();
|
||||
/* 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);
|
||||
/* Send output with hardcoded TTL/HL since we have no access to the pcb */
|
||||
ipX_output(isipv6, p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Send a TCP RESET packet (empty segment with RST flag set) over IPv6,
|
||||
* either to abort a connection or to show that there is no matching local
|
||||
* connection for a received segment.
|
||||
*
|
||||
* Called by tcp_abort() (to abort a local connection), tcp_input() (if no
|
||||
* matching local pcb was found), tcp_listen_input() (if incoming segment
|
||||
* has ACK flag set) and tcp_process() (received segment in the wrong state)
|
||||
*
|
||||
* Since a RST segment is in most cases not sent for an active connection,
|
||||
* tcp_rst() has a number of arguments that are taken from a tcp_pcb for
|
||||
* most other segment output functions.
|
||||
*
|
||||
* @param seqno the sequence number to use for the outgoing segment
|
||||
* @param ackno the acknowledge number to use for the outgoing segment
|
||||
* @param local_ip6 the local IPv6 address to send the segment from
|
||||
* @param remote_ip6 the remote IPv6 address to send the segment to
|
||||
* @param local_port the local TCP port to send the segment from
|
||||
* @param remote_port the remote TCP port to send the segment to
|
||||
*/
|
||||
void
|
||||
tcp_rst_ip6(u32_t seqno, u32_t ackno,
|
||||
ip6_addr_t *local_ip6, ip6_addr_t *remote_ip6,
|
||||
u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
|
||||
(p->len >= sizeof(struct tcp_hdr)));
|
||||
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
tcphdr->src = htons(local_port);
|
||||
tcphdr->dest = htons(remote_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
|
||||
tcphdr->wnd = PP_HTONS(TCP_WND);
|
||||
tcphdr->chksum = 0;
|
||||
tcphdr->urgp = 0;
|
||||
|
||||
/* chksum us mandatory over IPv6. */
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, local_ip6, remote_ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
snmp_inc_tcpoutrsts();
|
||||
/* Send output with hardcoded HL since we have no access to the pcb */
|
||||
ip6_output(p, local_ip6, remote_ip6, TCP_TTL, 0, IP6_NEXTH_TCP);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Requeue all unacked segments for retransmission
|
||||
*
|
||||
@@ -1495,11 +1376,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
struct tcp_hdr *tcphdr;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, TCP_DEBUG, &pcb->remote_ip);
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
|
||||
@@ -1513,41 +1390,18 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
}
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
}
|
||||
tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len,
|
||||
&pcb->local_ip, &pcb->remote_ip);
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip6_output_hinted(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP,
|
||||
&(pcb->addr_hint));
|
||||
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip6_output(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP);
|
||||
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||
0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
@@ -1574,11 +1428,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
u8_t is_fin;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, TCP_DEBUG, &pcb->remote_ip);
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
@@ -1616,41 +1466,19 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len,
|
||||
&pcb->local_ip, &pcb->remote_ip);
|
||||
#endif
|
||||
}
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip6_output_hinted(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP,
|
||||
&(pcb->addr_hint));
|
||||
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||
0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip6_output(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP);
|
||||
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
|
||||
476
src/core/udp.c
476
src/core/udp.c
@@ -57,7 +57,7 @@
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/icmp6.h"
|
||||
@@ -93,6 +93,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
u16_t src, dest;
|
||||
u8_t local_match;
|
||||
u8_t broadcast;
|
||||
u8_t for_us;
|
||||
|
||||
PERF_START;
|
||||
|
||||
@@ -114,7 +115,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
/* is broadcast packet ? */
|
||||
#if LWIP_IPV6
|
||||
broadcast = (ip_current_header() != NULL) && ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||
broadcast = !ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||
#else /* LWIP_IPV6 */
|
||||
broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||
#endif /* LWIP_IPV6 */
|
||||
@@ -129,17 +130,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
/* print the UDP source and destination */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
|
||||
if (ip_current_header() != NULL) {
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr());
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, ip6_current_dest_addr());
|
||||
}
|
||||
ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_dest_addr());
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest)));
|
||||
if (ip_current_header() != NULL) {
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr());
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, ip6_current_src_addr());
|
||||
}
|
||||
ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_src_addr());
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src)));
|
||||
|
||||
#if LWIP_DHCP
|
||||
@@ -152,13 +145,10 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
|
||||
/* accept the packe if
|
||||
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
|
||||
- inp->dhcp->pcb->remote == ANY or iphdr->src */
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
!pcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
((ip_addr_isany(&inp->dhcp->pcb->remote_ip.ip4) ||
|
||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip.ip4), ip_current_src_addr())))) {
|
||||
- inp->dhcp->pcb->remote == ANY or iphdr->src
|
||||
(no need to check for IPv6 since the dhcp struct always uses IPv4) */
|
||||
if (ipX_addr_isany(0, &inp->dhcp->pcb->remote_ip) ||
|
||||
ip_addr_cmp(ipX_2_ip(&(inp->dhcp->pcb->remote_ip)), ip_current_src_addr())) {
|
||||
pcb = inp->dhcp->pcb;
|
||||
}
|
||||
}
|
||||
@@ -177,36 +167,27 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
local_match = 0;
|
||||
/* print the PCB local and remote address */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb ("));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, &pcb->local_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG, &pcb->local_ip);
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG, &pcb->remote_ip);
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port));
|
||||
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
(ip6_addr_isany(&pcb->local_ip.ip6) ||
|
||||
((pcb->isipv6 && (ip_current_is_v6()) &&
|
||||
(ip6_addr_isany(ipX_2_ip6(&pcb->local_ip)) ||
|
||||
#if LWIP_IPV6_MLD
|
||||
ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
ip6_addr_cmp(ipX_2_ip6(&pcb->local_ip), ip6_current_dest_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((!broadcast && ip_addr_isany(&pcb->local_ip.ip4)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
((!broadcast && ipX_addr_isany(0, &pcb->local_ip)) ||
|
||||
ip_addr_cmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr()) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
@@ -224,19 +205,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
/* compare PCB remote addr+port to UDP source addr+port */
|
||||
if ((local_match != 0) &&
|
||||
(pcb->remote_port == src) &&
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
(ip6_addr_isany(&pcb->remote_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->remote_ip.ip6, ip6_current_src_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((ip_addr_isany(&pcb->remote_ip.ip4) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr())))))) {
|
||||
(pcb->remote_port == src) && IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||
(ipX_addr_isany(pcb->isipv6, &pcb->remote_ip) ||
|
||||
ipX_addr_cmp(pcb->isipv6, &pcb->remote_ip, ipX_current_src_addr()))) {
|
||||
/* the first fully matching PCB */
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of udp_pcbs so that is
|
||||
@@ -258,28 +229,24 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
/* Check checksum if this is a match or if it was directed at us. */
|
||||
if ((pcb != NULL) ||
|
||||
if (pcb != NULL) {
|
||||
for_us = 1;
|
||||
} else {
|
||||
#if LWIP_IPV6
|
||||
((ip6_current_header() != NULL) &&
|
||||
netif_matches_ip6_addr(inp, ip6_current_dest_addr())) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
(
|
||||
if (ip_current_is_v6()) {
|
||||
for_us = netif_matches_ip6_addr(inp, ip6_current_dest_addr());
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr()))) {
|
||||
{
|
||||
for_us = ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr());
|
||||
}
|
||||
}
|
||||
if (for_us) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||
#if LWIP_UDPLITE
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
((ip6_current_header() != NULL) &&
|
||||
(IP6H_NEXTH(ip6_current_header()) == IP_PROTO_UDPLITE)) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
(
|
||||
#endif /* LWIP_IPV6 */
|
||||
(IPH_PROTO(iphdr) == IP_PROTO_UDPLITE))) {
|
||||
/* Do the UDP Lite checksum */
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
#if LWIP_UDPLITE
|
||||
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
|
||||
/* Do the UDP Lite checksum */
|
||||
u16_t chklen = ntohs(udphdr->len);
|
||||
if (chklen < sizeof(struct udp_hdr)) {
|
||||
if (chklen == 0) {
|
||||
@@ -289,72 +256,26 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
} else {
|
||||
/* At least the UDP-Lite header must be covered by the
|
||||
checksum! (Again, see RFC 3828 chap. 3.1) */
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
goto chkerr;
|
||||
}
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo_partial(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
if (ipX_chksum_pseudo_partial(ip_current_is_v6(), p, IP_PROTO_UDPLITE,
|
||||
p->tot_len, chklen,
|
||||
ipX_current_src_addr(), ipX_current_dest_addr()) != 0) {
|
||||
goto chkerr;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (inet_chksum_pseudo_partial(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
#endif /* CHECKSUM_CHECK_UDP */
|
||||
} else
|
||||
#endif /* LWIP_UDPLITE */
|
||||
{
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len,
|
||||
ipX_current_src_addr(),
|
||||
ipX_current_dest_addr()) != 0) {
|
||||
goto chkerr;
|
||||
}
|
||||
}
|
||||
#endif /* CHECKSUM_CHECK_UDP */
|
||||
}
|
||||
#endif /* CHECKSUM_CHECK_UDP */
|
||||
if(pbuf_header(p, -UDP_HLEN)) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
@@ -376,15 +297,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
if SOF_REUSEADDR is set on the first match */
|
||||
struct udp_pcb *mpcb;
|
||||
u8_t p_header_changed = 0;
|
||||
s16_t hdrs_len;
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
hdrs_len = (s16_t)(ip6_current_header_tot_len() + UDP_HLEN);
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
hdrs_len = (s16_t)((IPH_HL(ip_current_header()) * 4) + UDP_HLEN);
|
||||
}
|
||||
s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN);
|
||||
for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
|
||||
if (mpcb != pcb) {
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
@@ -392,13 +305,13 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
#if LWIP_IPV6
|
||||
((mpcb->isipv6 &&
|
||||
(ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||
ip6_addr_cmp(&mpcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
ip6_addr_cmp(ipX_2_ip6(&mpcb->local_ip), ip6_current_dest_addr()))) ||
|
||||
(!mpcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((!broadcast && ip_addr_isany(&mpcb->local_ip.ip4)) ||
|
||||
ip_addr_cmp(&(mpcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
((!broadcast && ipX_addr_isany(0, &mpcb->local_ip)) ||
|
||||
ip_addr_cmp(ipX_2_ip(&mpcb->local_ip), ip_current_dest_addr()) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
@@ -470,23 +383,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
!ip6_addr_ismulticast(ip6_current_dest_addr()) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
!ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
#if LWIP_IPV6 && LWIP_ICMP6
|
||||
if (ip6_current_header() != NULL) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, ip6_current_header_tot_len() + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == ip6_current_header()", (p->payload == ip6_current_header()));
|
||||
icmp6_dest_unreach(p, ICMP6_DUR_PORT);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 && LWIP_ICMP6 */
|
||||
{
|
||||
#if LWIP_ICMP
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, (IPH_HL(ip_current_header()) * 4) + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == ip_current_header()", (p->payload == ip_current_header()));
|
||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
||||
#endif /* LWIP_ICMP */
|
||||
}
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, ip_current_header_tot_len() + UDP_HLEN);
|
||||
icmp_port_unreach(ip_current_is_v6(), p);
|
||||
}
|
||||
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
||||
UDP_STATS_INC(udp.proterr);
|
||||
@@ -499,6 +398,15 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
end:
|
||||
PERF_STOP("udp_input");
|
||||
return;
|
||||
chkerr:
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
PERF_STOP("udp_input");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,7 +431,7 @@ err_t
|
||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto(pcb, p, &pcb->remote_ip.ip4, pcb->remote_port);
|
||||
return udp_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port);
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
@@ -534,7 +442,7 @@ udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip.ip4, pcb->remote_port,
|
||||
return udp_sendto_chksum(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port,
|
||||
have_chksum, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
@@ -577,12 +485,12 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
/* find the outgoing network interface for this packet */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_ismulticast((ip6_addr_t *)dst_ip)) {
|
||||
if (ip6_addr_ismulticast(ip_2_ip6(dst_ip))) {
|
||||
/* For multicast, find a netif based on source address. */
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), &(pcb->local_ip.ip6));
|
||||
netif = ip6_route(ipX_2_ip6(&pcb->local_ip), ipX_2_ip6(&pcb->local_ip));
|
||||
}
|
||||
else {
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), (ip6_addr_t *)dst_ip);
|
||||
netif = ip6_route(ipX_2_ip6(&pcb->local_ip), ip_2_ip6(dst_ip));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -598,11 +506,7 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, (ip6_addr_t *)dst_ip);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ip_2_ipX(dst_ip));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("\n"));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
@@ -652,6 +556,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
ip_addr_t *src_ip;
|
||||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
u8_t ip_proto;
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
@@ -669,7 +574,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
err = udp_bind(pcb, &pcb->local_ip.ip4, pcb->local_port);
|
||||
err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
|
||||
return err;
|
||||
@@ -714,7 +619,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
(
|
||||
#if LWIP_IPV6_MLD
|
||||
(pcb->isipv6 &&
|
||||
ip6_addr_ismulticast((ip6_addr_t*)dst_ip)) ||
|
||||
ip6_addr_ismulticast(ip_2_ip6(dst_ip))) ||
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
(!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
@@ -729,8 +634,8 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&pcb->local_ip.ip6)) {
|
||||
src_ip =(ip_addr_t *)ip6_select_source_address(netif, (ip6_addr_t *)dst_ip);
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip)));
|
||||
if (src_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
if (q != p) {
|
||||
@@ -742,7 +647,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
} else {
|
||||
/* use UDP PCB local IPv6 address as source address, if still valid. */
|
||||
if (netif_matches_ip6_addr(netif, &(pcb->local_ip.ip6)) < 0) {
|
||||
if (netif_matches_ip6_addr(netif, ipX_2_ip6(&pcb->local_ip)) < 0) {
|
||||
/* Address isn't valid anymore. */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
@@ -751,18 +656,18 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
src_ip = (ip_addr_t *)&(pcb->local_ip.ip6);
|
||||
src_ip = ipX_2_ip(&pcb->local_ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4)) {
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* check if UDP PCB local IP address is correct
|
||||
* this could be an old address if netif->ip_addr has changed */
|
||||
if (!ip_addr_cmp(&(pcb->local_ip.ip4), &(netif->ip_addr))) {
|
||||
if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) {
|
||||
/* local_ip doesn't match, drop the packet */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
@@ -773,7 +678,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
return ERR_VAL;
|
||||
}
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip.ip4);
|
||||
src_ip = ipX_2_ip(&(pcb->local_ip));
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||
@@ -800,88 +705,51 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
udphdr->len = htons(chklen_hdr);
|
||||
/* calculate checksum */
|
||||
#if LWIP_IPV6
|
||||
/* Checksum is mandatory for IPv6. */
|
||||
if (pcb->isipv6) {
|
||||
udphdr->chksum = ip6_chksum_pseudo_partial(q, (ip6_addr_t *)src_ip, (ip6_addr_t *)dst_ip,
|
||||
IP6_NEXTH_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
||||
IP_PROTO_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
chklen = UDP_HLEN;
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
udphdr->chksum = ipX_chksum_pseudo_partial(pcb->isipv6, q, IP_PROTO_UDPLITE,
|
||||
q->tot_len, chklen, ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
}
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
}
|
||||
/* output to IP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, pcb->ttl, pcb->tos, IP6_NEXTH_UDPLITE, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
||||
ip_proto = IP_PROTO_UDPLITE;
|
||||
} else
|
||||
#endif /* LWIP_UDPLITE */
|
||||
{ /* UDP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||
udphdr->len = htons(q->tot_len);
|
||||
/* calculate checksum */
|
||||
#if LWIP_IPV6
|
||||
#if CHECKSUM_GEN_UDP
|
||||
/* Checksum is mandatory over IPv6. */
|
||||
if (pcb->isipv6) {
|
||||
if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = ip6_chksum_pseudo_partial(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, IP6_NEXTH_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
udpchksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDP,
|
||||
q->tot_len, UDP_HLEN, ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = ip6_chksum_pseudo(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, IP6_NEXTH_UDP, q->tot_len);
|
||||
udpchksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, q->tot_len,
|
||||
ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
@@ -890,52 +758,17 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udpchksum == 0x0000) {
|
||||
udpchksum = 0xffff;
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* output to IP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, pcb->ttl, pcb->tos, IP6_NEXTH_UDP, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_proto = IP_PROTO_UDP;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto));
|
||||
/* output to IP */
|
||||
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
|
||||
err = ipX_output_if(pcb->isipv6, q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif);
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
/* TODO: must this be increased even if error occured? */
|
||||
snmp_inc_udpoutdatagrams();
|
||||
|
||||
@@ -977,11 +810,7 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
u8_t rebind;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG | LWIP_DBG_TRACE, ip_2_ipX(ipaddr));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
|
||||
|
||||
rebind = 0;
|
||||
@@ -1005,22 +834,11 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
/* port matches that of PCB in list and REUSEADDR not set -> reject */
|
||||
else {
|
||||
#endif /* SO_REUSE */
|
||||
if ((ipcb->local_port == port) &&
|
||||
if ((ipcb->local_port == port) && IP_PCB_IPVER_EQ(pcb, ipcb) &&
|
||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
ipcb->isipv6 &&
|
||||
(ip6_addr_isany(&(ipcb->local_ip.ip6)) ||
|
||||
ip6_addr_isany((ip6_addr_t *)ipaddr) ||
|
||||
ip6_addr_cmp(&(ipcb->local_ip.ip6), (ip6_addr_t *)ipaddr))) ||
|
||||
(!pcb->isipv6 &&
|
||||
!ipcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&(ipcb->local_ip.ip4)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(ipcb->local_ip.ip4), ipaddr))))) {
|
||||
(ipX_addr_isany(ipcb->isipv6, &(ipcb->local_ip)) ||
|
||||
ipX_addr_isany(ipcb->isipv6, ip_2_ipX(ipaddr)) ||
|
||||
ipX_addr_cmp(ipcb->isipv6, &(ipcb->local_ip), ip_2_ipX(ipaddr)))) {
|
||||
/* other PCB already binds to this local IP and port */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||
@@ -1029,15 +847,7 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip.ip4, ipaddr);
|
||||
}
|
||||
ipX_addr_set_ipaddr(pcb->isipv6, &pcb->local_ip, ipaddr);
|
||||
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
@@ -1075,14 +885,11 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
udp_pcbs = pcb;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip);
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect an UDP PCB.
|
||||
*
|
||||
@@ -1106,21 +913,13 @@ udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if (pcb->local_port == 0) {
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip.ip4, pcb->local_port);
|
||||
err_t err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip.ip4, ipaddr);
|
||||
}
|
||||
ipX_addr_set_ipaddr(pcb->isipv6, &pcb->remote_ip, ipaddr);
|
||||
pcb->remote_port = port;
|
||||
pcb->flags |= UDP_FLAGS_CONNECTED;
|
||||
/** TODO: this functionality belongs in upper layers */
|
||||
@@ -1130,29 +929,27 @@ udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4) && !ip_addr_isany(&pcb->remote_ip.ip4)) {
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip)) && !ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) {
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(&(pcb->remote_ip.ip4))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.ip4.addr));
|
||||
if ((netif = ip_route(ipX_2_ip(&pcb->remote_ip))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n",
|
||||
ip4_addr_get_u32(ipX_2_ip(&pcb->remote_ip))));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||
is used to route output packets to the remote address. However, we
|
||||
might want to accept incoming packets on any interface! */
|
||||
pcb->local_ip.ip4 = netif->ip_addr;
|
||||
} else if (ip_addr_isany(&pcb->remote_ip.ip4)) {
|
||||
pcb->local_ip.ip4.addr = 0;
|
||||
ipX_addr_copy(0, pcb->local_ip, netif->ip_addr);
|
||||
} else if (ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) {
|
||||
ipX_addr_set_any(0, &pcb->local_ip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->remote_ip.ip6);
|
||||
}
|
||||
ipX_addr_debug_print(pcb->isipv6, UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
&pcb->remote_ip);
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
@@ -1177,15 +974,7 @@ void
|
||||
udp_disconnect(struct udp_pcb *pcb)
|
||||
{
|
||||
/* reset remote address association */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set_any(&pcb->remote_ip.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set_any(&pcb->remote_ip.ip4);
|
||||
}
|
||||
ipX_addr_set_any(pcb->isipv6, &pcb->remote_ip);
|
||||
pcb->remote_port = 0;
|
||||
/* mark PCB as unconnected */
|
||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||
@@ -1278,10 +1067,7 @@ udp_new_ip6(void)
|
||||
{
|
||||
struct udp_pcb *pcb;
|
||||
pcb = udp_new();
|
||||
/* could allocate UDP PCB? */
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
ip_set_v6(pcb, 1);
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
Reference in New Issue
Block a user