summaryrefslogtreecommitdiff
path: root/ext/lwip/src/core/ipv4
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-16 14:50:08 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-16 14:50:08 -0700
commitbc3d7d11fe13ce7b3a01b77e1002a78e53d99f83 (patch)
tree9e4da34ae7e734efe85d036ec6c6ca1208d10746 /ext/lwip/src/core/ipv4
parent490d20e8fb1c936324e3501196004592f46b3ff4 (diff)
downloadinfinitytier-bc3d7d11fe13ce7b3a01b77e1002a78e53d99f83.tar.gz
infinitytier-bc3d7d11fe13ce7b3a01b77e1002a78e53d99f83.zip
Remove netcon from dev branch. This is moving to its own new ZeroTierSDK repo for future release under the SDK name.
Diffstat (limited to 'ext/lwip/src/core/ipv4')
-rw-r--r--ext/lwip/src/core/ipv4/autoip.c528
-rw-r--r--ext/lwip/src/core/ipv4/icmp.c339
-rw-r--r--ext/lwip/src/core/ipv4/igmp.c805
-rw-r--r--ext/lwip/src/core/ipv4/inet.c42
-rw-r--r--ext/lwip/src/core/ipv4/inet_chksum.c450
-rw-r--r--ext/lwip/src/core/ipv4/ip.c924
-rw-r--r--ext/lwip/src/core/ipv4/ip_addr.c312
-rw-r--r--ext/lwip/src/core/ipv4/ip_frag.c863
8 files changed, 0 insertions, 4263 deletions
diff --git a/ext/lwip/src/core/ipv4/autoip.c b/ext/lwip/src/core/ipv4/autoip.c
deleted file mode 100644
index b122da27..00000000
--- a/ext/lwip/src/core/ipv4/autoip.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/**
- * @file
- * AutoIP Automatic LinkLocal IP Configuration
- *
- */
-
-/*
- *
- * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
- * 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.
- *
- * Author: Dominik Spies <kontakt@dspies.de>
- *
- * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
- * with RFC 3927.
- *
- *
- * Please coordinate changes and requests with Dominik Spies
- * <kontakt@dspies.de>
- */
-
-/*******************************************************************************
- * USAGE:
- *
- * define LWIP_AUTOIP 1 in your lwipopts.h
- *
- * If you don't use tcpip.c (so, don't call, you don't call tcpip_init):
- * - First, call autoip_init().
- * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces,
- * that should be defined in autoip.h.
- * I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
- * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
- *
- * Without DHCP:
- * - Call autoip_start() after netif_add().
- *
- * With DHCP:
- * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
- * - Configure your DHCP Client.
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/mem.h"
-#include "lwip/udp.h"
-#include "lwip/ip_addr.h"
-#include "lwip/netif.h"
-#include "lwip/autoip.h"
-#include "netif/etharp.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* 169.254.0.0 */
-#define AUTOIP_NET 0xA9FE0000
-/* 169.254.1.0 */
-#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)
-/* 169.254.254.255 */
-#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF)
-
-
-/** Pseudo random macro based on netif informations.
- * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
-#ifndef LWIP_AUTOIP_RAND
-#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
- ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
- ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
- ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
- (netif->autoip?netif->autoip->tried_llipaddr:0))
-#endif /* LWIP_AUTOIP_RAND */
-
-/**
- * Macro that generates the initial IP address to be tried by AUTOIP.
- * If you want to override this, define it to something else in lwipopts.h.
- */
-#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
-#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
- htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
- ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
-#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
-
-/* static functions */
-static void autoip_handle_arp_conflict(struct netif *netif);
-
-/* creates a pseudo random LL IP-Address for a network interface */
-static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr);
-
-/* sends an ARP probe */
-static err_t autoip_arp_probe(struct netif *netif);
-
-/* sends an ARP announce */
-static err_t autoip_arp_announce(struct netif *netif);
-
-/* configure interface for use with current LL IP-Address */
-static err_t autoip_bind(struct netif *netif);
-
-/* start sending probes for llipaddr */
-static void autoip_start_probing(struct netif *netif);
-
-
-/** Set a statically allocated struct autoip to work with.
- * Using this prevents autoip_start to allocate it using mem_malloc.
- *
- * @param netif the netif for which to set the struct autoip
- * @param dhcp (uninitialised) dhcp struct allocated by the application
- */
-void
-autoip_set_struct(struct netif *netif, struct autoip *autoip)
-{
- LWIP_ASSERT("netif != NULL", netif != NULL);
- LWIP_ASSERT("autoip != NULL", autoip != NULL);
- LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL);
-
- /* clear data structure */
- memset(autoip, 0, sizeof(struct autoip));
- /* autoip->state = AUTOIP_STATE_OFF; */
- netif->autoip = autoip;
-}
-
-/** Restart AutoIP client and check the next address (conflict detected)
- *
- * @param netif The netif under AutoIP control
- */
-static void
-autoip_restart(struct netif *netif)
-{
- netif->autoip->tried_llipaddr++;
- autoip_start(netif);
-}
-
-/**
- * Handle a IP address conflict after an ARP conflict detection
- */
-static void
-autoip_handle_arp_conflict(struct netif *netif)
-{
- /* Somehow detect if we are defending or retreating */
- unsigned char defend = 1; /* tbd */
-
- if (defend) {
- if (netif->autoip->lastconflict > 0) {
- /* retreat, there was a conflicting ARP in the last
- * DEFEND_INTERVAL seconds
- */
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
-
- /* TODO: close all TCP sessions */
- autoip_restart(netif);
- } else {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
- autoip_arp_announce(netif);
- netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
- }
- } else {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
- /* TODO: close all TCP sessions */
- autoip_restart(netif);
- }
-}
-
-/**
- * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
- *
- * @param netif network interface on which create the IP-Address
- * @param ipaddr ip address to initialize
- */
-static void
-autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr)
-{
- /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
- * compliant to RFC 3927 Section 2.1
- * We have 254 * 256 possibilities */
-
- u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
- addr += netif->autoip->tried_llipaddr;
- addr = AUTOIP_NET | (addr & 0xffff);
- /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
-
- if (addr < AUTOIP_RANGE_START) {
- addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
- }
- if (addr > AUTOIP_RANGE_END) {
- addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
- }
- LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
- (addr <= AUTOIP_RANGE_END));
- ip4_addr_set_u32(ipaddr, htonl(addr));
-
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
- ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
-}
-
-/**
- * Sends an ARP probe from a network interface
- *
- * @param netif network interface used to send the probe
- */
-static err_t
-autoip_arp_probe(struct netif *netif)
-{
- return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
- (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, &ethzero,
- &netif->autoip->llipaddr, ARP_REQUEST);
-}
-
-/**
- * Sends an ARP announce from a network interface
- *
- * @param netif network interface used to send the announce
- */
-static err_t
-autoip_arp_announce(struct netif *netif)
-{
- return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
- (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, &ethzero,
- &netif->autoip->llipaddr, ARP_REQUEST);
-}
-
-/**
- * Configure interface for use with current LL IP-Address
- *
- * @param netif network interface to configure with current LL IP-Address
- */
-static err_t
-autoip_bind(struct netif *netif)
-{
- struct autoip *autoip = netif->autoip;
- ip_addr_t sn_mask, gw_addr;
-
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
- ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
- ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
-
- IP4_ADDR(&sn_mask, 255, 255, 0, 0);
- IP4_ADDR(&gw_addr, 0, 0, 0, 0);
-
- netif_set_ipaddr(netif, &autoip->llipaddr);
- netif_set_netmask(netif, &sn_mask);
- netif_set_gw(netif, &gw_addr);
-
- /* bring the interface up */
- netif_set_up(netif);
-
- return ERR_OK;
-}
-
-/**
- * Start AutoIP client
- *
- * @param netif network interface on which start the AutoIP client
- */
-err_t
-autoip_start(struct netif *netif)
-{
- struct autoip *autoip = netif->autoip;
- err_t result = ERR_OK;
-
- if (netif_is_up(netif)) {
- netif_set_down(netif);
- }
-
- /* Set IP-Address, Netmask and Gateway to 0 to make sure that
- * ARP Packets are formed correctly
- */
- ip_addr_set_zero(&netif->ip_addr);
- ip_addr_set_zero(&netif->netmask);
- ip_addr_set_zero(&netif->gw);
-
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
- netif->name[1], (u16_t)netif->num));
- if (autoip == NULL) {
- /* no AutoIP client attached yet? */
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_start(): starting new AUTOIP client\n"));
- autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
- if (autoip == NULL) {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_start(): could not allocate autoip\n"));
- return ERR_MEM;
- }
- memset(autoip, 0, sizeof(struct autoip));
- /* store this AutoIP client in the netif */
- netif->autoip = autoip;
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
- } else {
- autoip->state = AUTOIP_STATE_OFF;
- autoip->ttw = 0;
- autoip->sent_num = 0;
- ip_addr_set_zero(&autoip->llipaddr);
- autoip->lastconflict = 0;
- }
-
- autoip_create_addr(netif, &(autoip->llipaddr));
- autoip_start_probing(netif);
-
- return result;
-}
-
-static void
-autoip_start_probing(struct netif *netif)
-{
- struct autoip *autoip = netif->autoip;
-
- autoip->state = AUTOIP_STATE_PROBING;
- autoip->sent_num = 0;
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
- ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
-
- /* time to wait to first probe, this is randomly
- * choosen out of 0 to PROBE_WAIT seconds.
- * compliant to RFC 3927 Section 2.2.1
- */
- autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
-
- /*
- * if we tried more then MAX_CONFLICTS we must limit our rate for
- * accquiring and probing address
- * compliant to RFC 3927 Section 2.2.1
- */
- if (autoip->tried_llipaddr > MAX_CONFLICTS) {
- autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
- }
-}
-
-/**
- * Handle a possible change in the network configuration.
- *
- * If there is an AutoIP address configured, take the interface down
- * and begin probing with the same address.
- */
-void
-autoip_network_changed(struct netif *netif)
-{
- if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
- netif_set_down(netif);
- autoip_start_probing(netif);
- }
-}
-
-/**
- * Stop AutoIP client
- *
- * @param netif network interface on which stop the AutoIP client
- */
-err_t
-autoip_stop(struct netif *netif)
-{
- netif->autoip->state = AUTOIP_STATE_OFF;
- netif_set_down(netif);
- return ERR_OK;
-}
-
-/**
- * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
- */
-void
-autoip_tmr()
-{
- struct netif *netif = netif_list;
- /* loop through netif's */
- while (netif != NULL) {
- /* only act on AutoIP configured interfaces */
- if (netif->autoip != NULL) {
- if (netif->autoip->lastconflict > 0) {
- netif->autoip->lastconflict--;
- }
-
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
- (u16_t)(netif->autoip->state), netif->autoip->ttw));
-
- switch(netif->autoip->state) {
- case AUTOIP_STATE_PROBING:
- if (netif->autoip->ttw > 0) {
- netif->autoip->ttw--;
- } else {
- if (netif->autoip->sent_num >= PROBE_NUM) {
- netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
- netif->autoip->sent_num = 0;
- netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
- ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
- } else {
- autoip_arp_probe(netif);
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_tmr() PROBING Sent Probe\n"));
- netif->autoip->sent_num++;
- /* calculate time to wait to next probe */
- netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
- ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
- PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
- }
- }
- break;
-
- case AUTOIP_STATE_ANNOUNCING:
- if (netif->autoip->ttw > 0) {
- netif->autoip->ttw--;
- } else {
- if (netif->autoip->sent_num == 0) {
- /* We are here the first time, so we waited ANNOUNCE_WAIT seconds
- * Now we can bind to an IP address and use it.
- *
- * autoip_bind calls netif_set_up. This triggers a gratuitous ARP
- * which counts as an announcement.
- */
- autoip_bind(netif);
- } else {
- autoip_arp_announce(netif);
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_tmr() ANNOUNCING Sent Announce\n"));
- }
- netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
- netif->autoip->sent_num++;
-
- if (netif->autoip->sent_num >= ANNOUNCE_NUM) {
- netif->autoip->state = AUTOIP_STATE_BOUND;
- netif->autoip->sent_num = 0;
- netif->autoip->ttw = 0;
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
- ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
- }
- }
- break;
- }
- }
- /* proceed to next network interface */
- netif = netif->next;
- }
-}
-
-/**
- * Handles every incoming ARP Packet, called by etharp_arp_input.
- *
- * @param netif network interface to use for autoip processing
- * @param hdr Incoming ARP packet
- */
-void
-autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
-{
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
- if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
- /* when ip.src == llipaddr && hw.src != netif->hwaddr
- *
- * when probing ip.dst == llipaddr && hw.src != netif->hwaddr
- * we have a conflict and must solve it
- */
- ip_addr_t sipaddr, dipaddr;
- struct eth_addr netifaddr;
- ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
-
- /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
- * structure packing (not using structure copy which breaks strict-aliasing rules).
- */
- IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
- IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
-
- if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
- ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
- (netif->autoip->sent_num == 0))) {
- /* RFC 3927 Section 2.2.1:
- * from beginning to after ANNOUNCE_WAIT
- * seconds we have a conflict if
- * ip.src == llipaddr OR
- * ip.dst == llipaddr && hw.src != own hwaddr
- */
- if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
- (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
- !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
- ("autoip_arp_reply(): Probe Conflict detected\n"));
- autoip_restart(netif);
- }
- } else {
- /* RFC 3927 Section 2.5:
- * in any state we have a conflict if
- * ip.src == llipaddr && hw.src != own hwaddr
- */
- if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
- !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
- ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
- autoip_handle_arp_conflict(netif);
- }
- }
- }
-}
-
-#endif /* LWIP_AUTOIP */
diff --git a/ext/lwip/src/core/ipv4/icmp.c b/ext/lwip/src/core/ipv4/icmp.c
deleted file mode 100644
index 47ba8571..00000000
--- a/ext/lwip/src/core/ipv4/icmp.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/**
- * @file
- * ICMP - Internet Control Message Protocol
- *
- */
-
-/*
- * 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>
- *
- */
-
-/* Some ICMP messages should be passed to the transport protocols. This
- is not implemented. */
-
-#include "lwip/opt.h"
-
-#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/icmp.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/ip.h"
-#include "lwip/def.h"
-#include "lwip/stats.h"
-#include "lwip/snmp.h"
-
-#include <string.h>
-
-/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
- * used to modify and send a response packet (and to 1 if this is not the case,
- * e.g. when link header is stripped of when receiving) */
-#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
-#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
-
-/* The amount of data from the original packet to return in a dest-unreachable */
-#define ICMP_DEST_UNREACH_DATASIZE 8
-
-static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
-
-/**
- * Processes ICMP input packets, called from ip_input().
- *
- * Currently only processes icmp echo requests and sends
- * out the echo response.
- *
- * @param p the icmp echo request packet, p->payload pointing to the ip header
- * @param inp the netif on which this packet was received
- */
-void
-icmp_input(struct pbuf *p, struct netif *inp)
-{
- u8_t type;
-#ifdef LWIP_DEBUG
- u8_t code;
-#endif /* LWIP_DEBUG */
- struct icmp_echo_hdr *iecho;
- struct ip_hdr *iphdr;
- s16_t hlen;
-
- ICMP_STATS_INC(icmp.recv);
- snmp_inc_icmpinmsgs();
-
-
- iphdr = (struct ip_hdr *)p->payload;
- hlen = IPH_HL(iphdr) * 4;
- if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
- goto lenerr;
- }
-
- type = *((u8_t *)p->payload);
-#ifdef LWIP_DEBUG
- code = *(((u8_t *)p->payload)+1);
-#endif /* LWIP_DEBUG */
- switch (type) {
- case ICMP_ER:
- /* This is OK, echo reply might have been parsed by a raw PCB
- (as obviously, an echo request has been sent, too). */
- break;
- case ICMP_ECHO:
-#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
- {
- int accepted = 1;
-#if !LWIP_MULTICAST_PING
- /* multicast destination address? */
- if (ip_addr_ismulticast(&current_iphdr_dest)) {
- accepted = 0;
- }
-#endif /* LWIP_MULTICAST_PING */
-#if !LWIP_BROADCAST_PING
- /* broadcast destination address? */
- if (ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
- accepted = 0;
- }
-#endif /* LWIP_BROADCAST_PING */
- /* broadcast or multicast destination address not acceptd? */
- if (!accepted) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
- ICMP_STATS_INC(icmp.err);
- pbuf_free(p);
- return;
- }
- }
-#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
- if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
- goto lenerr;
- }
- if (inet_chksum_pbuf(p) != 0) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
- pbuf_free(p);
- ICMP_STATS_INC(icmp.chkerr);
- snmp_inc_icmpinerrors();
- return;
- }
-#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
- if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
- /* p is not big enough to contain link headers
- * allocate a new one and copy p into it
- */
- struct pbuf *r;
- /* switch p->payload to ip header */
- if (pbuf_header(p, hlen)) {
- LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0);
- goto memerr;
- }
- /* allocate new packet buffer with space for link headers */
- r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
- if (r == NULL) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
- goto memerr;
- }
- LWIP_ASSERT("check that first pbuf can hold struct the ICMP header",
- (r->len >= hlen + sizeof(struct icmp_echo_hdr)));
- /* copy the whole packet including ip header */
- if (pbuf_copy(r, p) != ERR_OK) {
- LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
- goto memerr;
- }
- iphdr = (struct ip_hdr *)r->payload;
- /* switch r->payload back to icmp header */
- if (pbuf_header(r, -hlen)) {
- LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
- goto memerr;
- }
- /* free the original p */
- pbuf_free(p);
- /* we now have an identical copy of p that has room for link headers */
- p = r;
- } else {
- /* restore p->payload to point to icmp header */
- if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
- LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
- goto memerr;
- }
- }
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
- /* At this point, all checks are OK. */
- /* We generate an answer by switching the dest and src ip addresses,
- * setting the icmp type to ECHO_RESPONSE and updating the checksum. */
- iecho = (struct icmp_echo_hdr *)p->payload;
- ip_addr_copy(iphdr->src, *ip_current_dest_addr());
- ip_addr_copy(iphdr->dest, *ip_current_src_addr());
- ICMPH_TYPE_SET(iecho, ICMP_ER);
-#if CHECKSUM_GEN_ICMP
- /* adjust the checksum */
- if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
- iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
- } else {
- iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
- }
-#else /* CHECKSUM_GEN_ICMP */
- iecho->chksum = 0;
-#endif /* CHECKSUM_GEN_ICMP */
-
- /* Set the correct TTL and recalculate the header checksum. */
- IPH_TTL_SET(iphdr, ICMP_TTL);
- IPH_CHKSUM_SET(iphdr, 0);
-#if CHECKSUM_GEN_IP
- IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
-#endif /* CHECKSUM_GEN_IP */
-
- ICMP_STATS_INC(icmp.xmit);
- /* increase number of messages attempted to send */
- snmp_inc_icmpoutmsgs();
- /* increase number of echo replies attempted to send */
- snmp_inc_icmpoutechoreps();
-
- if(pbuf_header(p, hlen)) {
- LWIP_ASSERT("Can't move over header in packet", 0);
- } else {
- err_t ret;
- /* send an ICMP packet, src addr is the dest addr of the curren packet */
- ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL,
- ICMP_TTL, 0, IP_PROTO_ICMP, inp);
- if (ret != ERR_OK) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret));
- }
- }
- break;
- default:
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
- (s16_t)type, (s16_t)code));
- ICMP_STATS_INC(icmp.proterr);
- ICMP_STATS_INC(icmp.drop);
- }
- pbuf_free(p);
- return;
-lenerr:
- pbuf_free(p);
- ICMP_STATS_INC(icmp.lenerr);
- snmp_inc_icmpinerrors();
- return;
-#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
-memerr:
- pbuf_free(p);
- ICMP_STATS_INC(icmp.err);
- snmp_inc_icmpinerrors();
- return;
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
-}
-
-/**
- * Send an icmp 'destination unreachable' packet, called from ip_input() if
- * the transport layer protocol is unknown and from udp_input() if the local
- * port is not bound.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- * p->payload pointing to the IP header
- * @param t type of the 'unreachable' packet
- */
-void
-icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
-{
- icmp_send_response(p, ICMP_DUR, t);
-}
-
-#if IP_FORWARD || IP_REASSEMBLY
-/**
- * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
- *
- * @param p the input packet for which the 'time exceeded' should be sent,
- * p->payload pointing to the IP header
- * @param t type of the 'time exceeded' packet
- */
-void
-icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
-{
- icmp_send_response(p, ICMP_TE, t);
-}
-
-#endif /* IP_FORWARD || IP_REASSEMBLY */
-
-/**
- * Send an icmp packet in response to an incoming packet.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- * p->payload pointing to the IP header
- * @param type Type of the ICMP header
- * @param code Code of the ICMP header
- */
-static void
-icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
-{
- struct pbuf *q;
- struct ip_hdr *iphdr;
- /* we can use the echo header here */
- struct icmp_echo_hdr *icmphdr;
- ip_addr_t iphdr_src;
-
- /* ICMP header + IP header + 8 bytes of data */
- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
- PBUF_RAM);
- if (q == NULL) {
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
- return;
- }
- LWIP_ASSERT("check that first pbuf can hold icmp message",
- (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
-
- iphdr = (struct ip_hdr *)p->payload;
- LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
- ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
- LWIP_DEBUGF(ICMP_DEBUG, (" to "));
- ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
- LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
-
- icmphdr = (struct icmp_echo_hdr *)q->payload;
- icmphdr->type = type;
- icmphdr->code = code;
- icmphdr->id = 0;
- icmphdr->seqno = 0;
-
- /* copy fields from original packet */
- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
- IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
-
- /* calculate checksum */
- icmphdr->chksum = 0;
- icmphdr->chksum = inet_chksum(icmphdr, q->len);
- ICMP_STATS_INC(icmp.xmit);
- /* increase number of messages attempted to send */
- snmp_inc_icmpoutmsgs();
- /* increase number of destination unreachable messages attempted to send */
- snmp_inc_icmpouttimeexcds();
- ip_addr_copy(iphdr_src, iphdr->src);
- ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);
- pbuf_free(q);
-}
-
-#endif /* LWIP_ICMP */
diff --git a/ext/lwip/src/core/ipv4/igmp.c b/ext/lwip/src/core/ipv4/igmp.c
deleted file mode 100644
index 45bb5d95..00000000
--- a/ext/lwip/src/core/ipv4/igmp.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/**
- * @file
- * IGMP - Internet Group Management Protocol
- *
- */
-
-/*
- * Copyright (c) 2002 CITEL 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. Neither the name of CITEL Technologies Ltd nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``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 CITEL TECHNOLOGIES OR CONTRIBUTORS 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 a contribution to the lwIP TCP/IP stack.
- * The Swedish Institute of Computer Science and Adam Dunkels
- * are specifically granted permission to redistribute this
- * source code.
-*/
-
-/*-------------------------------------------------------------
-Note 1)
-Although the rfc requires V1 AND V2 capability
-we will only support v2 since now V1 is very old (August 1989)
-V1 can be added if required
-
-a debug print and statistic have been implemented to
-show this up.
--------------------------------------------------------------
--------------------------------------------------------------
-Note 2)
-A query for a specific group address (as opposed to ALLHOSTS)
-has now been implemented as I am unsure if it is required
-
-a debug print and statistic have been implemented to
-show this up.
--------------------------------------------------------------
--------------------------------------------------------------
-Note 3)
-The router alert rfc 2113 is implemented in outgoing packets
-but not checked rigorously incoming
--------------------------------------------------------------
-Steve Reynolds
-------------------------------------------------------------*/
-
-/*-----------------------------------------------------------------------------
- * RFC 988 - Host extensions for IP multicasting - V0
- * RFC 1054 - Host extensions for IP multicasting -
- * RFC 1112 - Host extensions for IP multicasting - V1
- * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard)
- * RFC 3376 - Internet Group Management Protocol, Version 3 - V3
- * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+
- * RFC 2113 - IP Router Alert Option -
- *----------------------------------------------------------------------------*/
-
-/*-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
-
-#include "lwip/opt.h"
-
-#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/igmp.h"
-#include "lwip/debug.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/ip.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/icmp.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
-#include "lwip/stats.h"
-
-#include "string.h"
-
-/*
- * IGMP constants
- */
-#define IGMP_TTL 1
-#define IGMP_MINLEN 8
-#define ROUTER_ALERT 0x9404U
-#define ROUTER_ALERTLEN 4
-
-/*
- * IGMP message types, including version number.
- */
-#define IGMP_MEMB_QUERY 0x11 /* Membership query */
-#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */
-#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */
-#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */
-
-/* Group membership states */
-#define IGMP_GROUP_NON_MEMBER 0
-#define IGMP_GROUP_DELAYING_MEMBER 1
-#define IGMP_GROUP_IDLE_MEMBER 2
-
-/**
- * IGMP packet format.
- */
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct igmp_msg {
- PACK_STRUCT_FIELD(u8_t igmp_msgtype);
- PACK_STRUCT_FIELD(u8_t igmp_maxresp);
- PACK_STRUCT_FIELD(u16_t igmp_checksum);
- PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
-
-
-static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
-static err_t igmp_remove_group(struct igmp_group *group);
-static void igmp_timeout( struct igmp_group *group);
-static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
-static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
-static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
-static void igmp_send(struct igmp_group *group, u8_t type);
-
-
-static struct igmp_group* igmp_group_list;
-static ip_addr_t allsystems;
-static ip_addr_t allrouters;
-
-
-/**
- * Initialize the IGMP module
- */
-void
-igmp_init(void)
-{
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n"));
-
- IP4_ADDR(&allsystems, 224, 0, 0, 1);
- IP4_ADDR(&allrouters, 224, 0, 0, 2);
-}
-
-#ifdef LWIP_DEBUG
-/**
- * Dump global IGMP groups list
- */
-void
-igmp_dump_group_list()
-{
- struct igmp_group *group = igmp_group_list;
-
- while (group != NULL) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
- ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
- LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
- group = group->next;
- }
- LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-}
-#else
-#define igmp_dump_group_list()
-#endif /* LWIP_DEBUG */
-
-/**
- * Start IGMP processing on interface
- *
- * @param netif network interface on which start IGMP processing
- */
-err_t
-igmp_start(struct netif *netif)
-{
- struct igmp_group* group;
-
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif));
-
- group = igmp_lookup_group(netif, &allsystems);
-
- if (group != NULL) {
- group->group_state = IGMP_GROUP_IDLE_MEMBER;
- group->use++;
-
- /* Allow the igmp messages at the MAC level */
- if (netif->igmp_mac_filter != NULL) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
- ip_addr_debug_print(IGMP_DEBUG, &allsystems);
- LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
- netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);
- }
-
- return ERR_OK;
- }
-
- return ERR_MEM;
-}
-
-/**
- * Stop IGMP processing on interface
- *
- * @param netif network interface on which stop IGMP processing
- */
-err_t
-igmp_stop(struct netif *netif)
-{
- struct igmp_group *group = igmp_group_list;
- struct igmp_group *prev = NULL;
- struct igmp_group *next;
-
- /* look for groups joined on this interface further down the list */
- while (group != NULL) {
- next = group->next;
- /* is it a group joined on this interface? */
- if (group->netif == netif) {
- /* is it the first group of the list? */
- if (group == igmp_group_list) {
- igmp_group_list = next;
- }
- /* is there a "previous" group defined? */
- if (prev != NULL) {
- prev->next = next;
- }
- /* disable the group at the MAC level */
- if (netif->igmp_mac_filter != NULL) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
- ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
- LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
- netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
- }
- /* free group */
- memp_free(MEMP_IGMP_GROUP, group);
- } else {
- /* change the "previous" */
- prev = group;
- }
- /* move to "next" */
- group = next;
- }
- return ERR_OK;
-}
-
-/**
- * Report IGMP memberships for this interface
- *
- * @param netif network interface on which report IGMP memberships
- */
-void
-igmp_report_groups(struct netif *netif)
-{
- struct igmp_group *group = igmp_group_list;
-
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
-
- while (group != NULL) {
- if (group->netif == netif) {
- igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
- }
- group = group->next;
- }
-}
-
-/**
- * Search for a group in the global igmp_group_list
- *
- * @param ifp the network interface for which to look
- * @param addr the group ip address to search for
- * @return a struct igmp_group* if the group has been found,
- * NULL if the group wasn't found.
- */
-struct igmp_group *
-igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr)
-{
- struct igmp_group *group = igmp_group_list;
-
- while (group != NULL) {
- if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
- return group;
- }
- group = group->next;
- }
-
- /* to be clearer, we return NULL here instead of
- * 'group' (which is also NULL at this point).
- */
- return NULL;
-}
-
-/**
- * Search for a specific igmp group and create a new one if not found-
- *
- * @param ifp the network interface for which to look
- * @param addr the group ip address to search
- * @return a struct igmp_group*,
- * NULL on memory error.
- */
-struct igmp_group *
-igmp_lookup_group(struct netif *ifp, ip_addr_t *addr)
-{
- struct igmp_group *group = igmp_group_list;
-
- /* Search if the group already exists */
- group = igmp_lookfor_group(ifp, addr);
- if (group != NULL) {
- /* Group already exists. */
- return group;
- }
-
- /* Group doesn't exist yet, create a new one */
- group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
- if (group != NULL) {
- group->netif = ifp;
- ip_addr_set(&(group->group_address), addr);
- group->timer = 0; /* Not running */
- group->group_state = IGMP_GROUP_NON_MEMBER;
- group->last_reporter_flag = 0;
- group->use = 0;
- group->next = igmp_group_list;
-
- igmp_group_list = group;
- }
-
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
- ip_addr_debug_print(IGMP_DEBUG, addr);
- LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));
-
- return group;
-}
-
-/**
- * Remove a group in the global igmp_group_list
- *
- * @param group the group to remove from the global igmp_group_list
- * @return ERR_OK if group was removed from the list, an err_t otherwise
- */
-static err_t
-igmp_remove_group(struct igmp_group *group)
-{
- err_t err = ERR_OK;
-
- /* Is it the first group? */
- if (igmp_group_list == group) {
- igmp_group_list = group->next;
- } else {
- /* look for group further down the list */
- struct igmp_group *tmpGroup;
- for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
- if (tmpGroup->next == group) {
- tmpGroup->next = group->next;
- break;
- }
- }
- /* Group not found in the global igmp_group_list */
- if (tmpGroup == NULL)
- err = ERR_ARG;
- }
- /* free group */
- memp_free(MEMP_IGMP_GROUP, group);
-
- return err;
-}
-
-/**
- * Called from ip_input() if a new IGMP packet is received.
- *
- * @param p received igmp packet, p->payload pointing to the ip header
- * @param inp network interface on which the packet was received
- * @param dest destination ip address of the igmp packet
- */
-void
-igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
-{
- struct ip_hdr * iphdr;
- struct igmp_msg* igmp;
- struct igmp_group* group;
- struct igmp_group* groupref;
-
- IGMP_STATS_INC(igmp.recv);
-
- /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
- iphdr = (struct ip_hdr *)p->payload;
- if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
- pbuf_free(p);
- IGMP_STATS_INC(igmp.lenerr);
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
- return;
- }
-
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
- ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
- LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
- ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
- LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
-
- /* Now calculate and check the checksum */
- igmp = (struct igmp_msg *)p->payload;
- if (inet_chksum(igmp, p->len)) {
- pbuf_free(p);
- IGMP_STATS_INC(igmp.chkerr);
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n"));
- return;
- }
-
- /* Packet is ok so find an existing group */
- group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */
-
- /* If group can be found or create... */
- if (!group) {
- pbuf_free(p);
- IGMP_STATS_INC(igmp.drop);
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
- return;
- }
-
- /* NOW ACT ON THE INCOMING MESSAGE TYPE... */
- switch (igmp->igmp_msgtype) {
- case IGMP_MEMB_QUERY: {
- /* IGMP_MEMB_QUERY to the "all systems" address ? */
- if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) {
- /* THIS IS THE GENERAL QUERY */
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
-
- if (igmp->igmp_maxresp == 0) {
- IGMP_STATS_INC(igmp.rx_v1);
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
- igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
- } else {
- IGMP_STATS_INC(igmp.rx_general);
- }
-
- groupref = igmp_group_list;
- while (groupref) {
- /* Do not send messages on the all systems group address! */
- if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
- igmp_delaying_member(groupref, igmp->igmp_maxresp);
- }
- groupref = groupref->next;
- }
- } else {
- /* IGMP_MEMB_QUERY to a specific group ? */
- if (!ip_addr_isany(&igmp->igmp_group_address)) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
- ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
- if (ip_addr_cmp(dest, &allsystems)) {
- ip_addr_t groupaddr;
- LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
- /* we first need to re-look for the group since we used dest last time */
- ip_addr_copy(groupaddr, igmp->igmp_group_address);
- group = igmp_lookfor_group(inp, &groupaddr);
- } else {
- LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
- }
-
- if (group != NULL) {
- IGMP_STATS_INC(igmp.rx_group);
- igmp_delaying_member(group, igmp->igmp_maxresp);
- } else {
- IGMP_STATS_INC(igmp.drop);
- }
- } else {
- IGMP_STATS_INC(igmp.proterr);
- }
- }
- break;
- }
- case IGMP_V2_MEMB_REPORT: {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
- IGMP_STATS_INC(igmp.rx_report);
- if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
- /* This is on a specific group we have already looked up */
- group->timer = 0; /* stopped */
- group->group_state = IGMP_GROUP_IDLE_MEMBER;
- group->last_reporter_flag = 0;
- }
- break;
- }
- default: {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
- igmp->igmp_msgtype, group->group_state, &group, group->netif));
- IGMP_STATS_INC(igmp.proterr);
- break;
- }
- }
-
- pbuf_free(p);
- return;
-}
-
-/**
- * Join a group on one network interface.
- *
- * @param ifaddr ip address of the network interface which should join a new group
- * @param groupaddr the ip address of the group which to join
- * @return ERR_OK if group was joined on the netif(s), an err_t otherwise
- */
-err_t
-igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
-{
- err_t err = ERR_VAL; /* no matching interface */
- struct igmp_group *group;
- struct netif *netif;
-
- /* make sure it is multicast address */
- LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
- LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
- /* loop through netif's */
- netif = netif_list;
- while (netif != NULL) {
- /* Should we join this interface ? */
- if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {
- /* find group or create a new one if not found */
- group = igmp_lookup_group(netif, groupaddr);
-
- if (group != NULL) {
- /* This should create a new group, check the state to make sure */
- if (group->group_state != IGMP_GROUP_NON_MEMBER) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
- } else {
- /* OK - it was new group */
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));
- ip_addr_debug_print(IGMP_DEBUG, groupaddr);
- LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-
- /* If first use of the group, allow the group at the MAC level */
- if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));
- ip_addr_debug_print(IGMP_DEBUG, groupaddr);
- LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
- netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
- }
-
- IGMP_STATS_INC(igmp.tx_join);
- igmp_send(group, IGMP_V2_MEMB_REPORT);
-
- igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
-
- /* Need to work out where this timer comes from */
- group->group_state = IGMP_GROUP_DELAYING_MEMBER;
- }
- /* Increment group use */
- group->use++;
- /* Join on this interface */
- err = ERR_OK;
- } else {
- /* Return an error even if some network interfaces are joined */
- /** @todo undo any other netif already joined */
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n"));
- return ERR_MEM;
- }
- }
- /* proceed to next network interface */
- netif = netif->next;
- }
-
- return err;
-}
-
-/**
- * Leave a group on one network interface.
- *
- * @param ifaddr ip address of the network interface which should leave a group
- * @param groupaddr the ip address of the group which to leave
- * @return ERR_OK if group was left on the netif(s), an err_t otherwise
- */
-err_t
-igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
-{
- err_t err = ERR_VAL; /* no matching interface */
- struct igmp_group *group;
- struct netif *netif;
-
- /* make sure it is multicast address */
- LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
- LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
- /* loop through netif's */
- netif = netif_list;
- while (netif != NULL) {
- /* Should we leave this interface ? */
- if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {
- /* find group */
- group = igmp_lookfor_group(netif, groupaddr);
-
- if (group != NULL) {
- /* Only send a leave if the flag is set according to the state diagram */
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));
- ip_addr_debug_print(IGMP_DEBUG, groupaddr);
- LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-
- /* If there is no other use of the group */
- if (group->use <= 1) {
- /* If we are the last reporter for this group */
- if (group->last_reporter_flag) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
- IGMP_STATS_INC(igmp.tx_leave);
- igmp_send(group, IGMP_LEAVE_GROUP);
- }
-
- /* Disable the group at the MAC level */
- if (netif->igmp_mac_filter != NULL) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));
- ip_addr_debug_print(IGMP_DEBUG, groupaddr);
- LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
- netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
- }
-
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: "));
- ip_addr_debug_print(IGMP_DEBUG, groupaddr);
- LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-
- /* Free the group */
- igmp_remove_group(group);
- } else {
- /* Decrement group use */
- group->use--;
- }
- /* Leave on this interface */
- err = ERR_OK;
- } else {
- /* It's not a fatal error on "leavegroup" */
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));
- }
- }
- /* proceed to next network interface */
- netif = netif->next;
- }
-
- return err;
-}
-
-/**
- * The igmp timer function (both for NO_SYS=1 and =0)
- * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default).
- */
-void
-igmp_tmr(void)
-{
- struct igmp_group *group = igmp_group_list;
-
- while (group != NULL) {
- if (group->timer > 0) {
- group->timer--;
- if (group->timer == 0) {
- igmp_timeout(group);
- }
- }
- group = group->next;
- }
-}
-
-/**
- * Called if a timeout for one group is reached.
- * Sends a report for this group.
- *
- * @param group an igmp_group for which a timeout is reached
- */
-static void
-igmp_timeout(struct igmp_group *group)
-{
- /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */
- if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
- ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));
- LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
-
- IGMP_STATS_INC(igmp.tx_report);
- igmp_send(group, IGMP_V2_MEMB_REPORT);
- }
-}
-
-/**
- * Start a timer for an igmp group
- *
- * @param group the igmp_group for which to start a timer
- * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with
- * every call to igmp_tmr())
- */
-static void
-igmp_start_timer(struct igmp_group *group, u8_t max_time)
-{
- /* ensure the input value is > 0 */
- if (max_time == 0) {
- max_time = 1;
- }
- /* ensure the random value is > 0 */
- group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
-}
-
-/**
- * Delaying membership report for a group if necessary
- *
- * @param group the igmp_group for which "delaying" membership report
- * @param maxresp query delay
- */
-static void
-igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
-{
- if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
- ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
- ((group->timer == 0) || (maxresp < group->timer)))) {
- igmp_start_timer(group, maxresp);
- group->group_state = IGMP_GROUP_DELAYING_MEMBER;
- }
-}
-
-
-/**
- * Sends an IP packet on a network interface. This function constructs the IP header
- * and calculates the IP header checksum. If the source IP address is NULL,
- * the IP address of the outgoing network interface is filled in as source address.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
- protocol header; if dest == IP_HDRINCL, p already includes an IP
- header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
- * IP address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- * @param netif the netif on which to send this packet
- * @return ERR_OK if the packet was sent OK
- * ERR_BUF if p doesn't have enough space for IP/LINK headers
- * returns errors returned by netif->output
- */
-static err_t
-igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif)
-{
- /* This is the "router alert" option */
- u16_t ra[2];
- ra[0] = PP_HTONS(ROUTER_ALERT);
- ra[1] = 0x0000; /* Router shall examine packet */
- IGMP_STATS_INC(igmp.xmit);
- return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
-}
-
-/**
- * Send an igmp packet to a specific group.
- *
- * @param group the group to which to send the packet
- * @param type the type of igmp packet to send
- */
-static void
-igmp_send(struct igmp_group *group, u8_t type)
-{
- struct pbuf* p = NULL;
- struct igmp_msg* igmp = NULL;
- ip_addr_t src = *IP_ADDR_ANY;
- ip_addr_t* dest = NULL;
-
- /* IP header + "router alert" option + IGMP header */
- p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
-
- if (p) {
- igmp = (struct igmp_msg *)p->payload;
- LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
- (p->len >= sizeof(struct igmp_msg)));
- ip_addr_copy(src, group->netif->ip_addr);
-
- if (type == IGMP_V2_MEMB_REPORT) {
- dest = &(group->group_address);
- ip_addr_copy(igmp->igmp_group_address, group->group_address);
- group->last_reporter_flag = 1; /* Remember we were the last to report */
- } else {
- if (type == IGMP_LEAVE_GROUP) {
- dest = &allrouters;
- ip_addr_copy(igmp->igmp_group_address, group->group_address);
- }
- }
-
- if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {
- igmp->igmp_msgtype = type;
- igmp->igmp_maxresp = 0;
- igmp->igmp_checksum = 0;
- igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
-
- igmp_ip_output_if(p, &src, dest, group->netif);
- }
-
- pbuf_free(p);
- } else {
- LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
- IGMP_STATS_INC(igmp.memerr);
- }
-}
-
-#endif /* LWIP_IGMP */
diff --git a/ext/lwip/src/core/ipv4/inet.c b/ext/lwip/src/core/ipv4/inet.c
deleted file mode 100644
index e283a576..00000000
--- a/ext/lwip/src/core/ipv4/inet.c
+++ /dev/null
@@ -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"
-
diff --git a/ext/lwip/src/core/ipv4/inet_chksum.c b/ext/lwip/src/core/ipv4/inet_chksum.c
deleted file mode 100644
index 960252f6..00000000
--- a/ext/lwip/src/core/ipv4/inet_chksum.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/**
- * @file
- * Incluse internet checksum 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_chksum.h"
-#include "lwip/def.h"
-
-#include <stddef.h>
-#include <string.h>
-
-/* These are some reference implementations of the checksum algorithm, with the
- * aim of being simple, correct and fully portable. Checksumming is the
- * first thing you would want to optimize for your platform. If you create
- * your own version, link it in and in your cc.h put:
- *
- * #define LWIP_CHKSUM <your_checksum_routine>
- *
- * Or you can select from the implementations below by defining
- * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
- */
-
-#ifndef LWIP_CHKSUM
-# define LWIP_CHKSUM lwip_standard_chksum
-# ifndef LWIP_CHKSUM_ALGORITHM
-# define LWIP_CHKSUM_ALGORITHM 2
-# endif
-#endif
-/* If none set: */
-#ifndef LWIP_CHKSUM_ALGORITHM
-# define LWIP_CHKSUM_ALGORITHM 0
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
-/**
- * lwip checksum
- *
- * @param dataptr points to start of data to be summed at any boundary
- * @param len length of data to be summed
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- *
- * @note accumulator size limits summable length to 64k
- * @note host endianess is irrelevant (p3 RFC1071)
- */
-static u16_t
-lwip_standard_chksum(void *dataptr, u16_t len)
-{
- u32_t acc;
- u16_t src;
- u8_t *octetptr;
-
- acc = 0;
- /* dataptr may be at odd or even addresses */
- octetptr = (u8_t*)dataptr;
- while (len > 1) {
- /* declare first octet as most significant
- thus assume network order, ignoring host order */
- src = (*octetptr) << 8;
- octetptr++;
- /* declare second octet as least significant */
- src |= (*octetptr);
- octetptr++;
- acc += src;
- len -= 2;
- }
- if (len > 0) {
- /* accumulate remaining octet */
- src = (*octetptr) << 8;
- acc += src;
- }
- /* add deferred carry bits */
- acc = (acc >> 16) + (acc & 0x0000ffffUL);
- if ((acc & 0xffff0000UL) != 0) {
- acc = (acc >> 16) + (acc & 0x0000ffffUL);
- }
- /* This maybe a little confusing: reorder sum using htons()
- instead of ntohs() since it has a little less call overhead.
- The caller must invert bits for Internet sum ! */
- return htons((u16_t)acc);
-}
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */
-/*
- * Curt McDowell
- * Broadcom Corp.
- * csm@broadcom.com
- *
- * IP checksum two bytes at a time with support for
- * unaligned buffer.
- * Works for len up to and including 0x20000.
- * by Curt McDowell, Broadcom Corp. 12/08/2005
- *
- * @param dataptr points to start of data to be summed at any boundary
- * @param len length of data to be summed
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- */
-
-static u16_t
-lwip_standard_chksum(void *dataptr, int len)
-{
- u8_t *pb = (u8_t *)dataptr;
- u16_t *ps, t = 0;
- u32_t sum = 0;
- int odd = ((mem_ptr_t)pb & 1);
-
- /* Get aligned to u16_t */
- if (odd && len > 0) {
- ((u8_t *)&t)[1] = *pb++;
- len--;
- }
-
- /* Add the bulk of the data */
- ps = (u16_t *)(void *)pb;
- while (len > 1) {
- sum += *ps++;
- len -= 2;
- }
-
- /* Consume left-over byte, if any */
- if (len > 0) {
- ((u8_t *)&t)[0] = *(u8_t *)ps;
- }
-
- /* Add end bytes */
- sum += t;
-
- /* Fold 32-bit sum to 16 bits
- calling this twice is propably faster than if statements... */
- sum = FOLD_U32T(sum);
- sum = FOLD_U32T(sum);
-
- /* Swap if alignment was odd */
- if (odd) {
- sum = SWAP_BYTES_IN_WORD(sum);
- }
-
- return (u16_t)sum;
-}
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */
-/**
- * An optimized checksum routine. Basically, it uses loop-unrolling on
- * the checksum loop, treating the head and tail bytes specially, whereas
- * the inner loop acts on 8 bytes at a time.
- *
- * @arg start of buffer to be checksummed. May be an odd byte address.
- * @len number of bytes in the buffer to be checksummed.
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- *
- * by Curt McDowell, Broadcom Corp. December 8th, 2005
- */
-
-static u16_t
-lwip_standard_chksum(void *dataptr, int len)
-{
- u8_t *pb = (u8_t *)dataptr;
- u16_t *ps, t = 0;
- u32_t *pl;
- u32_t sum = 0, tmp;
- /* starts at odd byte address? */
- int odd = ((mem_ptr_t)pb & 1);
-
- if (odd && len > 0) {
- ((u8_t *)&t)[1] = *pb++;
- len--;
- }
-
- ps = (u16_t *)pb;
-
- if (((mem_ptr_t)ps & 3) && len > 1) {
- sum += *ps++;
- len -= 2;
- }
-
- pl = (u32_t *)ps;
-
- while (len > 7) {
- tmp = sum + *pl++; /* ping */
- if (tmp < sum) {
- tmp++; /* add back carry */
- }
-
- sum = tmp + *pl++; /* pong */
- if (sum < tmp) {
- sum++; /* add back carry */
- }
-
- len -= 8;
- }
-
- /* make room in upper bits */
- sum = FOLD_U32T(sum);
-
- ps = (u16_t *)pl;
-
- /* 16-bit aligned word remaining? */
- while (len > 1) {
- sum += *ps++;
- len -= 2;
- }
-
- /* dangling tail byte remaining? */
- if (len > 0) { /* include odd byte */
- ((u8_t *)&t)[0] = *(u8_t *)ps;
- }
-
- sum += t; /* add end bytes */
-
- /* Fold 32-bit sum to 16 bits
- calling this twice is propably faster than if statements... */
- sum = FOLD_U32T(sum);
- sum = FOLD_U32T(sum);
-
- if (odd) {
- sum = SWAP_BYTES_IN_WORD(sum);
- }
-
- return (u16_t)sum;
-}
-#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)
-{
- 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) {
- LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
- (void *)q, (void *)q->next));
- acc += LWIP_CHKSUM(q->payload, q->len);
- /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
- /* just executing this next line is probably faster that the if statement needed
- to check whether we really need to execute it, and does no harm */
- acc = FOLD_U32T(acc);
- if (q->len % 2 != 0) {
- swapped = 1 - swapped;
- acc = SWAP_BYTES_IN_WORD(acc);
- }
- /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
- }
-
- 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);
-
- /* 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, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
- return (u16_t)~(acc & 0xffffUL);
-}
-
-/* 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_partial(struct pbuf *p,
- ip_addr_t *src, ip_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) {
- LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
- (void *)q, (void *)q->next));
- chklen = q->len;
- if (chklen > chksum_len) {
- chklen = chksum_len;
- }
- acc += LWIP_CHKSUM(q->payload, chklen);
- chksum_len -= chklen;
- LWIP_ASSERT("delete me", chksum_len < 0x7fff);
- /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
- /* fold the upper bit down */
- acc = FOLD_U32T(acc);
- if (q->len % 2 != 0) {
- swapped = 1 - swapped;
- acc = SWAP_BYTES_IN_WORD(acc);
- }
- /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
- }
-
- 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);
-
- /* 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, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
- return (u16_t)~(acc & 0xffffUL);
-}
-
-/* inet_chksum:
- *
- * Calculates the Internet checksum over a portion of memory. Used primarily for IP
- * and ICMP.
- *
- * @param dataptr start of the buffer to calculate the checksum (no alignment needed)
- * @param len length of the buffer to calculate the checksum
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-
-u16_t
-inet_chksum(void *dataptr, u16_t len)
-{
- return ~LWIP_CHKSUM(dataptr, len);
-}
-
-/**
- * Calculate a checksum over a chain of pbufs (without pseudo-header, much like
- * inet_chksum only pbufs are used).
- *
- * @param p pbuf chain over that the checksum should be calculated
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-inet_chksum_pbuf(struct pbuf *p)
-{
- u32_t acc;
- struct pbuf *q;
- u8_t swapped;
-
- acc = 0;
- swapped = 0;
- for(q = p; q != NULL; q = q->next) {
- acc += LWIP_CHKSUM(q->payload, q->len);
- 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);
- }
- return (u16_t)~(acc & 0xffffUL);
-}
-
-/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
- * like MEMCPY but generates a checksum at the same time. Since this is a
- * performance-sensitive function, you might want to create your own version
- * in assembly targeted at your hardware by defining it in lwipopts.h:
- * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
- */
-
-#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
-/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
- * For architectures with big caches, data might still be in cache when
- * generating the checksum after copying.
- */
-u16_t
-lwip_chksum_copy(void *dst, const void *src, u16_t len)
-{
- MEMCPY(dst, src, len);
- return LWIP_CHKSUM(dst, len);
-}
-#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
diff --git a/ext/lwip/src/core/ipv4/ip.c b/ext/lwip/src/core/ipv4/ip.c
deleted file mode 100644
index 0e09b3c0..00000000
--- a/ext/lwip/src/core/ipv4/ip.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/**
- * @file
- * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
- *
- * @see ip_frag.c
- *
- */
-
-/*
- * 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/ip.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/ip_frag.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/icmp.h"
-#include "lwip/igmp.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/tcp_impl.h"
-#include "lwip/snmp.h"
-#include "lwip/dhcp.h"
-#include "lwip/autoip.h"
-#include "lwip/stats.h"
-#include "arch/perf.h"
-
-#include <string.h>
-
-/** Set this to 0 in the rare case of wanting to call an extra function to
- * generate the IP checksum (in contrast to calculating it on-the-fly). */
-#ifndef LWIP_INLINE_IP_CHKSUM
-#define LWIP_INLINE_IP_CHKSUM 1
-#endif
-#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
-#define CHECKSUM_GEN_IP_INLINE 1
-#else
-#define CHECKSUM_GEN_IP_INLINE 0
-#endif
-
-#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
-#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
-
-/** Some defines for DHCP to let link-layer-addressed packets through while the
- * netif is down.
- * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
- * to return 1 if the port is accepted and 0 if the port is not accepted.
- */
-#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
-/* accept DHCP client port and custom port */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
- || (LWIP_IP_ACCEPT_UDP_PORT(port)))
-#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-/* accept custom port only */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port))
-#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-/* accept DHCP client port only */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
-#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-
-#else /* LWIP_DHCP */
-#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;
-
-/** The IP header ID of the next outgoing IP packet */
-static u16_t ip_id;
-
-/**
- * Finds the appropriate network interface for a given IP address. It
- * searches the list of network interfaces linearly. A match is found
- * if the masked IP address of the network interface equals the masked
- * IP address given to the function.
- *
- * @param dest the destination IP address for which to find the route
- * @return the netif on which to send to reach dest
- */
-struct netif *
-ip_route(ip_addr_t *dest)
-{
- struct netif *netif;
-
-#ifdef LWIP_HOOK_IP4_ROUTE
- netif = LWIP_HOOK_IP4_ROUTE(dest);
- if (netif != NULL) {
- return netif;
- }
-#endif
-
- /* iterate through netifs */
- for (netif = netif_list; netif != NULL; netif = netif->next) {
- /* network mask matches? */
- if (netif_is_up(netif)) {
- if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
- /* return netif on which to forward IP packet */
- return netif;
- }
- }
- }
- if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
- IP_STATS_INC(ip.rterr);
- snmp_inc_ipoutnoroutes();
- return NULL;
- }
- /* no matching netif found, use default netif */
- return netif_default;
-}
-
-#if IP_FORWARD
-/**
- * Determine whether an IP address is in a reserved set of addresses
- * that may not be forwarded, or whether datagrams to that destination
- * may be forwarded.
- * @param p the packet to forward
- * @param dest the destination IP address
- * @return 1: can forward 0: discard
- */
-static int
-ip_canforward(struct pbuf *p)
-{
- u32_t addr = ip4_addr_get_u32(ip_current_dest_addr());
-
- if (p->flags & PBUF_FLAG_LLBCAST) {
- /* don't route link-layer broadcasts */
- return 0;
- }
- if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) {
- /* don't route link-layer multicasts unless the destination address is an IP
- multicast address */
- return 0;
- }
- if (IP_EXPERIMENTAL(addr)) {
- return 0;
- }
- if (IP_CLASSA(addr)) {
- u32_t net = addr & IP_CLASSA_NET;
- if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) {
- /* don't route loopback packets */
- return 0;
- }
- }
- return 1;
-}
-
-/**
- * Forwards an IP packet. It finds an appropriate route for the
- * packet, decrements the TTL value of the packet, adjusts the
- * checksum and outputs the packet on the appropriate interface.
- *
- * @param p the packet to forward (p->payload points to IP header)
- * @param iphdr the IP header of the input packet
- * @param inp the netif on which this packet was received
- */
-static void
-ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
-{
- struct netif *netif;
-
- PERF_START;
-
- if (!ip_canforward(p)) {
- goto return_noroute;
- }
-
- /* RFC3927 2.7: do not forward link-local addresses */
- if (ip_addr_islinklocal(&current_iphdr_dest)) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
- ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
- goto return_noroute;
- }
-
- /* Find network interface where to forward this IP packet to. */
- netif = ip_route(&current_iphdr_dest);
- 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(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
- ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
- /* @todo: send ICMP_DUR_NET? */
- goto return_noroute;
- }
-#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
- /* Do not forward packets onto the same network interface on which
- * they arrived. */
- if (netif == inp) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
- goto return_noroute;
- }
-#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
-
- /* decrement TTL */
- IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
- /* send ICMP if TTL == 0 */
- if (IPH_TTL(iphdr) == 0) {
- snmp_inc_ipinhdrerrors();
-#if LWIP_ICMP
- /* Don't send ICMP messages in response to ICMP messages */
- if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
- icmp_time_exceeded(p, ICMP_TE_TTL);
- }
-#endif /* LWIP_ICMP */
- return;
- }
-
- /* Incrementally update the IP checksum. */
- if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
- IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
- } else {
- IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
- }
-
- LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
- ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
-
- IP_STATS_INC(ip.fw);
- IP_STATS_INC(ip.xmit);
- snmp_inc_ipforwdatagrams();
-
- PERF_STOP("ip_forward");
- /* don't fragment if interface has mtu set to 0 [loopif] */
- if (netif->mtu && (p->tot_len > netif->mtu)) {
- if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) {
-#if IP_FRAG
- ip_frag(p, netif, ip_current_dest_addr());
-#else /* IP_FRAG */
- /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */
-#endif /* IP_FRAG */
- } else {
- /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */
- icmp_dest_unreach(p, ICMP_DUR_FRAG);
- }
- return;
- }
- /* transmit pbuf on chosen interface */
- netif->output(netif, p, &current_iphdr_dest);
- return;
-return_noroute:
- snmp_inc_ipoutnoroutes();
-}
-#endif /* IP_FORWARD */
-
-/**
- * This function is called by the network interface device driver when
- * an IP packet is received. The function does the basic checks of the
- * IP header such as packet size being at least larger than the header
- * size etc. If the packet was not destined for us, the packet is
- * forwarded (using ip_forward). The IP checksum is always checked.
- *
- * Finally, the packet is sent to the upper layer protocol input function.
- *
- * @param p the received IP packet (p->payload points to IP header)
- * @param inp the netif on which this packet was received
- * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
- * processed, but currently always returns ERR_OK)
- */
-err_t
-ip_input(struct pbuf *p, struct netif *inp)
-{
- struct ip_hdr *iphdr;
- struct netif *netif;
- u16_t iphdr_hlen;
- u16_t iphdr_len;
-#if IP_ACCEPT_LINK_LAYER_ADDRESSING
- int check_ip_src=1;
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
-
- IP_STATS_INC(ip.recv);
- snmp_inc_ipinreceives();
-
- /* identify the IP header */
- iphdr = (struct ip_hdr *)p->payload;
- if (IPH_V(iphdr) != 4) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
- ip_debug_print(p);
- pbuf_free(p);
- IP_STATS_INC(ip.err);
- IP_STATS_INC(ip.drop);
- snmp_inc_ipinhdrerrors();
- return ERR_OK;
- }
-
-#ifdef LWIP_HOOK_IP4_INPUT
- if (LWIP_HOOK_IP4_INPUT(p, inp)) {
- /* the packet has been eaten */
- return ERR_OK;
- }
-#endif
-
- /* obtain IP header length in number of 32-bit words */
- iphdr_hlen = IPH_HL(iphdr);
- /* calculate IP header length in bytes */
- iphdr_hlen *= 4;
- /* obtain ip length in bytes */
- iphdr_len = ntohs(IPH_LEN(iphdr));
-
- /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
- if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
- if (iphdr_hlen > p->len) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
- iphdr_hlen, p->len));
- }
- if (iphdr_len > p->tot_len) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
- iphdr_len, p->tot_len));
- }
- /* free (drop) packet pbufs */
- pbuf_free(p);
- IP_STATS_INC(ip.lenerr);
- IP_STATS_INC(ip.drop);
- snmp_inc_ipindiscards();
- return ERR_OK;
- }
-
- /* verify checksum */
-#if CHECKSUM_CHECK_IP
- if (inet_chksum(iphdr, iphdr_hlen) != 0) {
-
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
- ip_debug_print(p);
- pbuf_free(p);
- IP_STATS_INC(ip.chkerr);
- IP_STATS_INC(ip.drop);
- snmp_inc_ipinhdrerrors();
- return ERR_OK;
- }
-#endif
-
- /* Trim pbuf. This should have been done at the netif layer,
- * but we'll do it anyway just to be sure that its done. */
- 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);
-
- /* match packet against an interface, i.e. is this packet for us? */
-#if LWIP_IGMP
- if (ip_addr_ismulticast(&current_iphdr_dest)) {
- if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
- netif = inp;
- } else {
- netif = NULL;
- }
- } else
-#endif /* LWIP_IGMP */
- {
- /* start trying with inp. if that's not acceptable, start walking the
- list of configured netifs.
- 'first' is used as a boolean to mark whether we started walking the list */
- int first = 1;
- netif = inp;
- do {
- LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
- ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
- ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
- ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
- ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
-
- /* 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(&current_iphdr_dest, &(netif->ip_addr)) ||
- /* or broadcast on this interface network address? */
- ip_addr_isbroadcast(&current_iphdr_dest, 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 */
- break;
- }
-#if LWIP_AUTOIP
- /* connections to link-local addresses must persist after changing
- the netif's address (RFC3927 ch. 1.9) */
- if ((netif->autoip != NULL) &&
- ip_addr_cmp(&current_iphdr_dest, &(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 */
- break;
- }
-#endif /* LWIP_AUTOIP */
- }
- if (first) {
- first = 0;
- netif = netif_list;
- } else {
- netif = netif->next;
- }
- if (netif == inp) {
- netif = netif->next;
- }
- } while(netif != NULL);
- }
-
-#if IP_ACCEPT_LINK_LAYER_ADDRESSING
- /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
- * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
- * According to RFC 1542 section 3.1.1, referred by RFC 2131).
- *
- * If you want to accept private broadcast communication while a netif is down,
- * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
- *
- * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
- */
- if (netif == NULL) {
- /* remote port is DHCP server? */
- if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
- struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
- ntohs(udphdr->dest)));
- if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
- netif = inp;
- check_ip_src = 0;
- }
- }
- }
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
-
- /* 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(&current_iphdr_src))
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
- { if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
- (ip_addr_ismulticast(&current_iphdr_src))) {
- /* 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 */
- pbuf_free(p);
- IP_STATS_INC(ip.drop);
- snmp_inc_ipinaddrerrors();
- snmp_inc_ipindiscards();
- return ERR_OK;
- }
- }
-
- /* packet not for us? */
- if (netif == NULL) {
- /* packet not for us, route or discard */
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
-#if IP_FORWARD
- /* non-broadcast packet? */
- if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
- /* try to forward IP packet on (other) interfaces */
- ip_forward(p, iphdr, inp);
- } else
-#endif /* IP_FORWARD */
- {
- snmp_inc_ipinaddrerrors();
- snmp_inc_ipindiscards();
- }
- pbuf_free(p);
- return ERR_OK;
- }
- /* packet consists of multiple fragments? */
- if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
-#if IP_REASSEMBLY /* packet fragment reassembly code present? */
- LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
- ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
- /* reassemble the packet*/
- p = ip_reass(p);
- /* packet not fully reassembled yet? */
- if (p == NULL) {
- return ERR_OK;
- }
- iphdr = (struct ip_hdr *)p->payload;
-#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
- pbuf_free(p);
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
- ntohs(IPH_OFFSET(iphdr))));
- IP_STATS_INC(ip.opterr);
- IP_STATS_INC(ip.drop);
- /* unsupported protocol feature */
- snmp_inc_ipinunknownprotos();
- return ERR_OK;
-#endif /* IP_REASSEMBLY */
- }
-
-#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
-
-#if LWIP_IGMP
- /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
- if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
-#else
- if (iphdr_hlen > IP_HLEN) {
-#endif /* LWIP_IGMP */
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
- pbuf_free(p);
- IP_STATS_INC(ip.opterr);
- IP_STATS_INC(ip.drop);
- /* unsupported protocol feature */
- snmp_inc_ipinunknownprotos();
- return ERR_OK;
- }
-#endif /* IP_OPTIONS_ALLOWED == 0 */
-
- /* send to upper layers */
- LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
- 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;
-
-#if LWIP_RAW
- /* raw input did not eat the packet? */
- if (raw_input(p, inp) == 0)
-#endif /* LWIP_RAW */
- {
- switch (IPH_PROTO(iphdr)) {
-#if LWIP_UDP
- case IP_PROTO_UDP:
-#if LWIP_UDPLITE
- case IP_PROTO_UDPLITE:
-#endif /* LWIP_UDPLITE */
- snmp_inc_ipindelivers();
- udp_input(p, inp);
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case IP_PROTO_TCP:
- snmp_inc_ipindelivers();
- tcp_input(p, inp);
- break;
-#endif /* LWIP_TCP */
-#if LWIP_ICMP
- case IP_PROTO_ICMP:
- snmp_inc_ipindelivers();
- icmp_input(p, inp);
- break;
-#endif /* LWIP_ICMP */
-#if LWIP_IGMP
- case IP_PROTO_IGMP:
- igmp_input(p, inp, &current_iphdr_dest);
- break;
-#endif /* LWIP_IGMP */
- default:
-#if LWIP_ICMP
- /* send ICMP destination protocol unreachable unless is was a broadcast */
- if (!ip_addr_isbroadcast(&current_iphdr_dest, inp) &&
- !ip_addr_ismulticast(&current_iphdr_dest)) {
- p->payload = iphdr;
- icmp_dest_unreach(p, ICMP_DUR_PROTO);
- }
-#endif /* LWIP_ICMP */
- pbuf_free(p);
-
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
-
- IP_STATS_INC(ip.proterr);
- IP_STATS_INC(ip.drop);
- snmp_inc_ipinunknownprotos();
- }
- }
-
- current_netif = NULL;
- current_header = NULL;
- ip_addr_set_any(&current_iphdr_src);
- ip_addr_set_any(&current_iphdr_dest);
-
- return ERR_OK;
-}
-
-/**
- * Sends an IP packet on a network interface. This function constructs
- * the IP header and calculates the IP header checksum. If the source
- * IP address is NULL, the IP address of the outgoing network
- * interface is filled in as source address.
- * If the destination IP address is IP_HDRINCL, p is assumed to already
- * include an IP header and p->payload points to it instead of the data.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
- protocol header; if dest == IP_HDRINCL, p already includes an IP
- header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
- * IP address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- * @param netif the netif on which to send this packet
- * @return ERR_OK if the packet was sent OK
- * ERR_BUF if p doesn't have enough space for IP/LINK headers
- * returns errors returned by netif->output
- *
- * @note ip_id: RFC791 "some host may be able to simply use
- * unique identifiers independent of destination"
- */
-err_t
-ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
- u8_t ttl, u8_t tos,
- u8_t proto, struct netif *netif)
-{
-#if IP_OPTIONS_SEND
- return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
-}
-
-/**
- * Same as ip_output_if() but with the possibility to include IP options:
- *
- * @ param ip_options pointer to the IP options, copied into the IP header
- * @ param optlen length of ip_options
- */
-err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
- u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
- u16_t optlen)
-{
-#endif /* IP_OPTIONS_SEND */
- struct ip_hdr *iphdr;
- ip_addr_t dest_addr;
-#if CHECKSUM_GEN_IP_INLINE
- u32_t chk_sum = 0;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
- /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
- gets altered as the packet is passed down the stack */
- LWIP_ASSERT("p->ref == 1", p->ref == 1);
-
- snmp_inc_ipoutrequests();
-
- /* Should the IP header be generated or is it already included in p? */
- if (dest != IP_HDRINCL) {
- u16_t ip_hlen = IP_HLEN;
-#if IP_OPTIONS_SEND
- u16_t optlen_aligned = 0;
- if (optlen != 0) {
-#if CHECKSUM_GEN_IP_INLINE
- int i;
-#endif /* CHECKSUM_GEN_IP_INLINE */
- /* round up to a multiple of 4 */
- optlen_aligned = ((optlen + 3) & ~3);
- ip_hlen += optlen_aligned;
- /* First write in the IP options */
- if (pbuf_header(p, optlen_aligned)) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
- IP_STATS_INC(ip.err);
- snmp_inc_ipoutdiscards();
- return ERR_BUF;
- }
- MEMCPY(p->payload, ip_options, optlen);
- if (optlen < optlen_aligned) {
- /* zero the remaining bytes */
- memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
- }
-#if CHECKSUM_GEN_IP_INLINE
- for (i = 0; i < optlen_aligned/2; i++) {
- chk_sum += ((u16_t*)p->payload)[i];
- }
-#endif /* CHECKSUM_GEN_IP_INLINE */
- }
-#endif /* IP_OPTIONS_SEND */
- /* generate IP header */
- if (pbuf_header(p, IP_HLEN)) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
-
- IP_STATS_INC(ip.err);
- snmp_inc_ipoutdiscards();
- return ERR_BUF;
- }
-
- iphdr = (struct ip_hdr *)p->payload;
- LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
- (p->len >= sizeof(struct ip_hdr)));
-
- IPH_TTL_SET(iphdr, ttl);
- IPH_PROTO_SET(iphdr, proto);
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += LWIP_MAKE_U16(proto, ttl);
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
- /* dest cannot be NULL here */
- ip_addr_copy(iphdr->dest, *dest);
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
- chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
- IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
- IPH_TOS_SET(iphdr, tos);
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
-#endif /* CHECKSUM_GEN_IP_INLINE */
- IPH_LEN_SET(iphdr, htons(p->tot_len));
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += iphdr->_len;
-#endif /* CHECKSUM_GEN_IP_INLINE */
- IPH_OFFSET_SET(iphdr, 0);
- IPH_ID_SET(iphdr, htons(ip_id));
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += iphdr->_id;
-#endif /* CHECKSUM_GEN_IP_INLINE */
- ++ip_id;
-
- if (ip_addr_isany(src)) {
- ip_addr_copy(iphdr->src, netif->ip_addr);
- } else {
- /* src cannot be NULL here */
- ip_addr_copy(iphdr->src, *src);
- }
-
-#if CHECKSUM_GEN_IP_INLINE
- chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
- chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
- chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
- chk_sum = (chk_sum >> 16) + chk_sum;
- chk_sum = ~chk_sum;
- iphdr->_chksum = chk_sum; /* network order */
-#else /* CHECKSUM_GEN_IP_INLINE */
- IPH_CHKSUM_SET(iphdr, 0);
-#if CHECKSUM_GEN_IP
- IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
-#endif
-#endif /* CHECKSUM_GEN_IP_INLINE */
- } else {
- /* IP header already included in p */
- iphdr = (struct ip_hdr *)p->payload;
- ip_addr_copy(dest_addr, iphdr->dest);
- dest = &dest_addr;
- }
-
- IP_STATS_INC(ip.xmit);
-
- LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
- ip_debug_print(p);
-
-#if ENABLE_LOOPBACK
- if (ip_addr_cmp(dest, &netif->ip_addr)) {
- /* Packet to self, enqueue it for loopback */
- LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
- return netif_loop_output(netif, p, dest);
- }
-#if LWIP_IGMP
- if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
- netif_loop_output(netif, p, dest);
- }
-#endif /* LWIP_IGMP */
-#endif /* ENABLE_LOOPBACK */
-#if IP_FRAG
- /* don't fragment if interface has mtu set to 0 [loopif] */
- if (netif->mtu && (p->tot_len > netif->mtu)) {
- return ip_frag(p, netif, dest);
- }
-#endif /* IP_FRAG */
-
- LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
- return netif->output(netif, p, dest);
-}
-
-/**
- * Simple interface to ip_output_if. It finds the outgoing network
- * interface and calls upon ip_output_if to do the actual work.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
- protocol header; if dest == IP_HDRINCL, p already includes an IP
- header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
- * IP address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- *
- * @return ERR_RTE if no route is found
- * see ip_output_if() for more return values
- */
-err_t
-ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
- u8_t ttl, u8_t tos, u8_t proto)
-{
- struct netif *netif;
-
- /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
- gets altered as the packet is passed down the stack */
- LWIP_ASSERT("p->ref == 1", p->ref == 1);
-
- if ((netif = ip_route(dest)) == NULL) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
- IP_STATS_INC(ip.rterr);
- return ERR_RTE;
- }
-
- return ip_output_if(p, src, dest, ttl, tos, proto, netif);
-}
-
-#if LWIP_NETIF_HWADDRHINT
-/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
- * before calling ip_output_if.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
- protocol header; if dest == IP_HDRINCL, p already includes an IP
- header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
- * IP address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- * @param addr_hint address hint pointer set to netif->addr_hint before
- * calling ip_output_if()
- *
- * @return ERR_RTE if no route is found
- * see ip_output_if() for more return values
- */
-err_t
-ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
- u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
-{
- struct netif *netif;
- err_t err;
-
- /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
- gets altered as the packet is passed down the stack */
- LWIP_ASSERT("p->ref == 1", p->ref == 1);
-
- if ((netif = ip_route(dest)) == NULL) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
- IP_STATS_INC(ip.rterr);
- return ERR_RTE;
- }
-
- NETIF_SET_HWADDRHINT(netif, addr_hint);
- err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
- NETIF_SET_HWADDRHINT(netif, NULL);
-
- return err;
-}
-#endif /* LWIP_NETIF_HWADDRHINT*/
-
-#if IP_DEBUG
-/* Print an IP header by using LWIP_DEBUGF
- * @param p an IP packet, p->payload pointing to the IP header
- */
-void
-ip_debug_print(struct pbuf *p)
-{
- struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
-
- LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
- LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
- IPH_V(iphdr),
- IPH_HL(iphdr),
- IPH_TOS(iphdr),
- ntohs(IPH_LEN(iphdr))));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
- LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
- ntohs(IPH_ID(iphdr)),
- ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
- ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
- ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
- ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
- LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
- IPH_TTL(iphdr),
- IPH_PROTO(iphdr),
- ntohs(IPH_CHKSUM(iphdr))));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
- LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
- ip4_addr1_16(&iphdr->src),
- ip4_addr2_16(&iphdr->src),
- ip4_addr3_16(&iphdr->src),
- ip4_addr4_16(&iphdr->src)));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
- LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
- ip4_addr1_16(&iphdr->dest),
- ip4_addr2_16(&iphdr->dest),
- ip4_addr3_16(&iphdr->dest),
- ip4_addr4_16(&iphdr->dest)));
- LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-}
-#endif /* IP_DEBUG */
diff --git a/ext/lwip/src/core/ipv4/ip_addr.c b/ext/lwip/src/core/ipv4/ip_addr.c
deleted file mode 100644
index 8f633ff2..00000000
--- a/ext/lwip/src/core/ipv4/ip_addr.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/**
- * @file
- * This is the IPv4 address tools implementation.
- *
- */
-
-/*
- * 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/ip_addr.h"
-#include "lwip/netif.h"
-
-/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
-const ip_addr_t ip_addr_any = { IPADDR_ANY };
-const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST };
-
-/**
- * Determine if an address is a broadcast address on a network interface
- *
- * @param addr address to be checked
- * @param netif the network interface against which the address is checked
- * @return returns non-zero if the address is a broadcast address
- */
-u8_t
-ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)
-{
- ip_addr_t ipaddr;
- ip4_addr_set_u32(&ipaddr, addr);
-
- /* all ones (broadcast) or all zeroes (old skool broadcast) */
- if ((~addr == IPADDR_ANY) ||
- (addr == IPADDR_ANY)) {
- return 1;
- /* no broadcast support on this network interface? */
- } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
- /* the given address cannot be a broadcast address
- * nor can we check against any broadcast addresses */
- return 0;
- /* address matches network interface address exactly? => no broadcast */
- } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) {
- return 0;
- /* on the same (sub) network... */
- } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask))
- /* ...and host identifier bits are all ones? =>... */
- && ((addr & ~ip4_addr_get_u32(&netif->netmask)) ==
- (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) {
- /* => network broadcast address */
- return 1;
- } else {
- return 0;
- }
-}
-
-/** Checks if a netmask is valid (starting with ones, then only zeros)
- *
- * @param netmask the IPv4 netmask to check (in network byte order!)
- * @return 1 if the netmask is valid, 0 if it is not
- */
-u8_t
-ip4_addr_netmask_valid(u32_t netmask)
-{
- u32_t mask;
- u32_t nm_hostorder = lwip_htonl(netmask);
-
- /* first, check for the first zero */
- for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
- if ((nm_hostorder & mask) == 0) {
- break;
- }
- }
- /* then check that there is no one */
- for (; mask != 0; mask >>= 1) {
- if ((nm_hostorder & mask) != 0) {
- /* there is a one after the first zero -> invalid */
- return 0;
- }
- }
- /* no one after the first zero -> valid */
- return 1;
-}
-
-/* Here for now until needed in other places in lwIP */
-#ifndef isprint
-#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
-#define isprint(c) in_range(c, 0x20, 0x7f)
-#define isdigit(c) in_range(c, '0', '9')
-#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
-#define islower(c) in_range(c, 'a', 'z')
-#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#endif
-
-/**
- * Ascii internet address interpretation routine.
- * The value returned is in network order.
- *
- * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
- * @return ip address in network order
- */
-u32_t
-ipaddr_addr(const char *cp)
-{
- ip_addr_t val;
-
- if (ipaddr_aton(cp, &val)) {
- return ip4_addr_get_u32(&val);
- }
- return (IPADDR_NONE);
-}
-
-/**
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- *
- * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
- * @param addr pointer to which to save the ip address in network order
- * @return 1 if cp could be converted to addr, 0 on failure
- */
-int
-ipaddr_aton(const char *cp, ip_addr_t *addr)
-{
- u32_t val;
- u8_t base;
- char c;
- u32_t parts[4];
- u32_t *pp = parts;
-
- c = *cp;
- for (;;) {
- /*
- * Collect number up to ``.''.
- * Values are specified as for C:
- * 0x=hex, 0=octal, 1-9=decimal.
- */
- if (!isdigit(c))
- return (0);
- val = 0;
- base = 10;
- if (c == '0') {
- c = *++cp;
- if (c == 'x' || c == 'X') {
- base = 16;
- c = *++cp;
- } else
- base = 8;
- }
- for (;;) {
- if (isdigit(c)) {
- val = (val * base) + (int)(c - '0');
- c = *++cp;
- } else if (base == 16 && isxdigit(c)) {
- val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
- c = *++cp;
- } else
- break;
- }
- if (c == '.') {
- /*
- * Internet format:
- * a.b.c.d
- * a.b.c (with c treated as 16 bits)
- * a.b (with b treated as 24 bits)
- */
- if (pp >= parts + 3) {
- return (0);
- }
- *pp++ = val;
- c = *++cp;
- } else
- break;
- }
- /*
- * Check for trailing characters.
- */
- if (c != '\0' && !isspace(c)) {
- return (0);
- }
- /*
- * Concoct the address according to
- * the number of parts specified.
- */
- switch (pp - parts + 1) {
-
- case 0:
- return (0); /* initial nondigit */
-
- case 1: /* a -- 32 bits */
- break;
-
- case 2: /* a.b -- 8.24 bits */
- if (val > 0xffffffUL) {
- return (0);
- }
- val |= parts[0] << 24;
- break;
-
- case 3: /* a.b.c -- 8.8.16 bits */
- if (val > 0xffff) {
- return (0);
- }
- val |= (parts[0] << 24) | (parts[1] << 16);
- break;
-
- case 4: /* a.b.c.d -- 8.8.8.8 bits */
- if (val > 0xff) {
- return (0);
- }
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
- break;
- default:
- LWIP_ASSERT("unhandled", 0);
- break;
- }
- if (addr) {
- ip4_addr_set_u32(addr, htonl(val));
- }
- return (1);
-}
-
-/**
- * Convert numeric IP address into decimal dotted ASCII representation.
- * returns ptr to static buffer; not reentrant!
- *
- * @param addr ip address in network order to convert
- * @return pointer to a global static (!) buffer that holds the ASCII
- * represenation of addr
- */
-char *
-ipaddr_ntoa(const ip_addr_t *addr)
-{
- static char str[16];
- return ipaddr_ntoa_r(addr, str, 16);
-}
-
-/**
- * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
- *
- * @param addr ip address in network order to convert
- * @param buf target buffer where the string is stored
- * @param buflen length of buf
- * @return either pointer to buf which now holds the ASCII
- * representation of addr or NULL if buf was too small
- */
-char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
-{
- u32_t s_addr;
- char inv[3];
- char *rp;
- u8_t *ap;
- u8_t rem;
- u8_t n;
- u8_t i;
- int len = 0;
-
- s_addr = ip4_addr_get_u32(addr);
-
- rp = buf;
- ap = (u8_t *)&s_addr;
- for(n = 0; n < 4; n++) {
- i = 0;
- do {
- rem = *ap % (u8_t)10;
- *ap /= (u8_t)10;
- inv[i++] = '0' + rem;
- } while(*ap);
- while(i--) {
- if (len++ >= buflen) {
- return NULL;
- }
- *rp++ = inv[i];
- }
- if (len++ >= buflen) {
- return NULL;
- }
- *rp++ = '.';
- ap++;
- }
- *--rp = 0;
- return buf;
-}
diff --git a/ext/lwip/src/core/ipv4/ip_frag.c b/ext/lwip/src/core/ipv4/ip_frag.c
deleted file mode 100644
index 8d184345..00000000
--- a/ext/lwip/src/core/ipv4/ip_frag.c
+++ /dev/null
@@ -1,863 +0,0 @@
-/**
- * @file
- * This is the IPv4 packet segmentation and reassembly implementation.
- *
- */
-
-/*
- * 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: Jani Monoses <jani@iv.ro>
- * Simon Goldschmidt
- * original reassembly code by Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-#include "lwip/ip_frag.h"
-#include "lwip/def.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/snmp.h"
-#include "lwip/stats.h"
-#include "lwip/icmp.h"
-
-#include <string.h>
-
-#if IP_REASSEMBLY
-/**
- * The IP reassembly code currently has the following limitations:
- * - IP header options are not supported
- * - fragments must not overlap (e.g. due to different routes),
- * currently, overlapping or duplicate fragments are thrown away
- * if IP_REASS_CHECK_OVERLAP=1 (the default)!
- *
- * @todo: work with IP header options
- */
-
-/** Setting this to 0, you can turn off checking the fragments for overlapping
- * regions. The code gets a little smaller. Only use this if you know that
- * overlapping won't occur on your network! */
-#ifndef IP_REASS_CHECK_OVERLAP
-#define IP_REASS_CHECK_OVERLAP 1
-#endif /* IP_REASS_CHECK_OVERLAP */
-
-/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
- * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
- * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
- * is set to 1, so one datagram can be reassembled at a time, only. */
-#ifndef IP_REASS_FREE_OLDEST
-#define IP_REASS_FREE_OLDEST 1
-#endif /* IP_REASS_FREE_OLDEST */
-
-#define IP_REASS_FLAG_LASTFRAG 0x01
-
-/** This is a helper struct which holds the starting
- * offset and the ending offset of this fragment to
- * easily chain the fragments.
- * It has the same packing requirements as the IP header, since it replaces
- * the IP header in memory in incoming fragments (after copying it) to keep
- * track of the various fragments. (-> If the IP header doesn't need packing,
- * this struct doesn't need packing, too.)
- */
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct ip_reass_helper {
- PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
- PACK_STRUCT_FIELD(u16_t start);
- PACK_STRUCT_FIELD(u16_t end);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
-
-#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \
- (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \
- ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \
- IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0
-
-/* global variables */
-static struct ip_reassdata *reassdatagrams;
-static u16_t ip_reass_pbufcount;
-
-/* function prototypes */
-static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
-static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
-
-/**
- * Reassembly timer base function
- * for both NO_SYS == 0 and 1 (!).
- *
- * Should be called every 1000 msec (defined by IP_TMR_INTERVAL).
- */
-void
-ip_reass_tmr(void)
-{
- struct ip_reassdata *r, *prev = NULL;
-
- r = reassdatagrams;
- while (r != NULL) {
- /* Decrement the timer. Once it reaches 0,
- * clean up the incomplete fragment assembly */
- if (r->timer > 0) {
- r->timer--;
- LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer));
- prev = r;
- r = r->next;
- } else {
- /* reassembly timed out */
- struct ip_reassdata *tmp;
- LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n"));
- tmp = r;
- /* get the next pointer before freeing */
- r = r->next;
- /* free the helper struct and all enqueued pbufs */
- ip_reass_free_complete_datagram(tmp, prev);
- }
- }
-}
-
-/**
- * Free a datagram (struct ip_reassdata) and all its pbufs.
- * Updates the total count of enqueued pbufs (ip_reass_pbufcount),
- * SNMP counters and sends an ICMP time exceeded packet.
- *
- * @param ipr datagram to free
- * @param prev the previous datagram in the linked list
- * @return the number of pbufs freed
- */
-static int
-ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
-{
- u16_t pbufs_freed = 0;
- u8_t clen;
- struct pbuf *p;
- struct ip_reass_helper *iprh;
-
- LWIP_ASSERT("prev != ipr", prev != ipr);
- if (prev != NULL) {
- LWIP_ASSERT("prev->next == ipr", prev->next == ipr);
- }
-
- snmp_inc_ipreasmfails();
-#if LWIP_ICMP
- iprh = (struct ip_reass_helper *)ipr->p->payload;
- if (iprh->start == 0) {
- /* The first fragment was received, send ICMP time exceeded. */
- /* First, de-queue the first pbuf from r->p. */
- p = ipr->p;
- ipr->p = iprh->next_pbuf;
- /* Then, copy the original header into it. */
- SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
- icmp_time_exceeded(p, ICMP_TE_FRAG);
- clen = pbuf_clen(p);
- LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
- pbufs_freed += clen;
- pbuf_free(p);
- }
-#endif /* LWIP_ICMP */
-
- /* First, free all received pbufs. The individual pbufs need to be released
- separately as they have not yet been chained */
- p = ipr->p;
- while (p != NULL) {
- struct pbuf *pcur;
- iprh = (struct ip_reass_helper *)p->payload;
- pcur = p;
- /* get the next pointer before freeing */
- p = iprh->next_pbuf;
- clen = pbuf_clen(pcur);
- LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
- pbufs_freed += clen;
- pbuf_free(pcur);
- }
- /* Then, unchain the struct ip_reassdata from the list and free it. */
- ip_reass_dequeue_datagram(ipr, prev);
- LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed);
- ip_reass_pbufcount -= pbufs_freed;
-
- return pbufs_freed;
-}
-
-#if IP_REASS_FREE_OLDEST
-/**
- * Free the oldest datagram to make room for enqueueing new fragments.
- * The datagram 'fraghdr' belongs to is not freed!
- *
- * @param fraghdr IP header of the current fragment
- * @param pbufs_needed number of pbufs needed to enqueue
- * (used for freeing other datagrams if not enough space)
- * @return the number of pbufs freed
- */
-static int
-ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
-{
- /* @todo Can't we simply remove the last datagram in the
- * linked list behind reassdatagrams?
- */
- struct ip_reassdata *r, *oldest, *prev;
- int pbufs_freed = 0, pbufs_freed_current;
- int other_datagrams;
-
- /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
- * but don't free the datagram that 'fraghdr' belongs to! */
- do {
- oldest = NULL;
- prev = NULL;
- other_datagrams = 0;
- r = reassdatagrams;
- while (r != NULL) {
- if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) {
- /* Not the same datagram as fraghdr */
- other_datagrams++;
- if (oldest == NULL) {
- oldest = r;
- } else if (r->timer <= oldest->timer) {
- /* older than the previous oldest */
- oldest = r;
- }
- }
- if (r->next != NULL) {
- prev = r;
- }
- r = r->next;
- }
- if (oldest != NULL) {
- pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev);
- pbufs_freed += pbufs_freed_current;
- }
- } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
- return pbufs_freed;
-}
-#endif /* IP_REASS_FREE_OLDEST */
-
-/**
- * Enqueues a new fragment into the fragment queue
- * @param fraghdr points to the new fragments IP hdr
- * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space)
- * @return A pointer to the queue location into which the fragment was enqueued
- */
-static struct ip_reassdata*
-ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
-{
- struct ip_reassdata* ipr;
- /* No matching previous fragment found, allocate a new reassdata struct */
- ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
- if (ipr == NULL) {
-#if IP_REASS_FREE_OLDEST
- if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
- ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
- }
- if (ipr == NULL)
-#endif /* IP_REASS_FREE_OLDEST */
- {
- IPFRAG_STATS_INC(ip_frag.memerr);
- LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n"));
- return NULL;
- }
- }
- memset(ipr, 0, sizeof(struct ip_reassdata));
- ipr->timer = IP_REASS_MAXAGE;
-
- /* enqueue the new structure to the front of the list */
- ipr->next = reassdatagrams;
- reassdatagrams = ipr;
- /* copy the ip header for later tests and input */
- /* @todo: no ip options supported? */
- SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN);
- return ipr;
-}
-
-/**
- * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs.
- * @param ipr points to the queue entry to dequeue
- */
-static void
-ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
-{
-
- /* dequeue the reass struct */
- if (reassdatagrams == ipr) {
- /* it was the first in the list */
- reassdatagrams = ipr->next;
- } else {
- /* it wasn't the first, so it must have a valid 'prev' */
- LWIP_ASSERT("sanity check linked list", prev != NULL);
- prev->next = ipr->next;
- }
-
- /* now we can free the ip_reass struct */
- memp_free(MEMP_REASSDATA, ipr);
-}
-
-/**
- * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list
- * will grow over time as new pbufs are rx.
- * Also checks that the datagram passes basic continuity checks (if the last
- * fragment was received at least once).
- * @param root_p points to the 'root' pbuf for the current datagram being assembled.
- * @param new_p points to the pbuf for the current fragment
- * @return 0 if invalid, >0 otherwise
- */
-static int
-ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
-{
- struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
- struct pbuf *q;
- u16_t offset,len;
- struct ip_hdr *fraghdr;
- int valid = 1;
-
- /* Extract length and fragment offset from current fragment */
- fraghdr = (struct ip_hdr*)new_p->payload;
- len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
- offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
-
- /* overwrite the fragment's ip header from the pbuf with our helper struct,
- * and setup the embedded helper structure. */
- /* make sure the struct ip_reass_helper fits into the IP header */
- LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN",
- sizeof(struct ip_reass_helper) <= IP_HLEN);
- iprh = (struct ip_reass_helper*)new_p->payload;
- iprh->next_pbuf = NULL;
- iprh->start = offset;
- iprh->end = offset + len;
-
- /* Iterate through until we either get to the end of the list (append),
- * or we find on with a larger offset (insert). */
- for (q = ipr->p; q != NULL;) {
- iprh_tmp = (struct ip_reass_helper*)q->payload;
- if (iprh->start < iprh_tmp->start) {
- /* the new pbuf should be inserted before this */
- iprh->next_pbuf = q;
- if (iprh_prev != NULL) {
- /* not the fragment with the lowest offset */
-#if IP_REASS_CHECK_OVERLAP
- if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
- /* fragment overlaps with previous or following, throw away */
- goto freepbuf;
- }
-#endif /* IP_REASS_CHECK_OVERLAP */
- iprh_prev->next_pbuf = new_p;
- } else {
- /* fragment with the lowest offset */
- ipr->p = new_p;
- }
- break;
- } else if(iprh->start == iprh_tmp->start) {
- /* received the same datagram twice: no need to keep the datagram */
- goto freepbuf;
-#if IP_REASS_CHECK_OVERLAP
- } else if(iprh->start < iprh_tmp->end) {
- /* overlap: no need to keep the new datagram */
- goto freepbuf;
-#endif /* IP_REASS_CHECK_OVERLAP */
- } else {
- /* Check if the fragments received so far have no wholes. */
- if (iprh_prev != NULL) {
- if (iprh_prev->end != iprh_tmp->start) {
- /* There is a fragment missing between the current
- * and the previous fragment */
- valid = 0;
- }
- }
- }
- q = iprh_tmp->next_pbuf;
- iprh_prev = iprh_tmp;
- }
-
- /* If q is NULL, then we made it to the end of the list. Determine what to do now */
- if (q == NULL) {
- if (iprh_prev != NULL) {
- /* this is (for now), the fragment with the highest offset:
- * chain it to the last fragment */
-#if IP_REASS_CHECK_OVERLAP
- LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
-#endif /* IP_REASS_CHECK_OVERLAP */
- iprh_prev->next_pbuf = new_p;
- if (iprh_prev->end != iprh->start) {
- valid = 0;
- }
- } else {
-#if IP_REASS_CHECK_OVERLAP
- LWIP_ASSERT("no previous fragment, this must be the first fragment!",
- ipr->p == NULL);
-#endif /* IP_REASS_CHECK_OVERLAP */
- /* this is the first fragment we ever received for this ip datagram */
- ipr->p = new_p;
- }
- }
-
- /* At this point, the validation part begins: */
- /* If we already received the last fragment */
- if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) {
- /* and had no wholes so far */
- if (valid) {
- /* then check if the rest of the fragments is here */
- /* Check if the queue starts with the first datagram */
- if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) {
- valid = 0;
- } else {
- /* and check that there are no wholes after this datagram */
- iprh_prev = iprh;
- q = iprh->next_pbuf;
- while (q != NULL) {
- iprh = (struct ip_reass_helper*)q->payload;
- if (iprh_prev->end != iprh->start) {
- valid = 0;
- break;
- }
- iprh_prev = iprh;
- q = iprh->next_pbuf;
- }
- /* if still valid, all fragments are received
- * (because to the MF==0 already arrived */
- if (valid) {
- LWIP_ASSERT("sanity check", ipr->p != NULL);
- LWIP_ASSERT("sanity check",
- ((struct ip_reass_helper*)ipr->p->payload) != iprh);
- LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
- iprh->next_pbuf == NULL);
- LWIP_ASSERT("validate_datagram:datagram end!=datagram len",
- iprh->end == ipr->datagram_len);
- }
- }
- }
- /* If valid is 0 here, there are some fragments missing in the middle
- * (since MF == 0 has already arrived). Such datagrams simply time out if
- * no more fragments are received... */
- return valid;
- }
- /* If we come here, not all fragments were received, yet! */
- return 0; /* not yet valid! */
-#if IP_REASS_CHECK_OVERLAP
-freepbuf:
- ip_reass_pbufcount -= pbuf_clen(new_p);
- pbuf_free(new_p);
- return 0;
-#endif /* IP_REASS_CHECK_OVERLAP */
-}
-
-/**
- * Reassembles incoming IP fragments into an IP datagram.
- *
- * @param p points to a pbuf chain of the fragment
- * @return NULL if reassembly is incomplete, ? otherwise
- */
-struct pbuf *
-ip_reass(struct pbuf *p)
-{
- struct pbuf *r;
- struct ip_hdr *fraghdr;
- struct ip_reassdata *ipr;
- struct ip_reass_helper *iprh;
- u16_t offset, len;
- u8_t clen;
- struct ip_reassdata *ipr_prev = NULL;
-
- IPFRAG_STATS_INC(ip_frag.recv);
- snmp_inc_ipreasmreqds();
-
- fraghdr = (struct ip_hdr*)p->payload;
-
- if ((IPH_HL(fraghdr) * 4) != IP_HLEN) {
- LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n"));
- IPFRAG_STATS_INC(ip_frag.err);
- goto nullreturn;
- }
-
- offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
- len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
-
- /* Check if we are allowed to enqueue more datagrams. */
- clen = pbuf_clen(p);
- if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
-#if IP_REASS_FREE_OLDEST
- if (!ip_reass_remove_oldest_datagram(fraghdr, clen) ||
- ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS))
-#endif /* IP_REASS_FREE_OLDEST */
- {
- /* No datagram could be freed and still too many pbufs enqueued */
- LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n",
- ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS));
- IPFRAG_STATS_INC(ip_frag.memerr);
- /* @todo: send ICMP time exceeded here? */
- /* drop this pbuf */
- goto nullreturn;
- }
- }
-
- /* Look for the datagram the fragment belongs to in the current datagram queue,
- * remembering the previous in the queue for later dequeueing. */
- for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) {
- /* Check if the incoming fragment matches the one currently present
- in the reassembly buffer. If so, we proceed with copying the
- fragment into the buffer. */
- if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
- LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
- ntohs(IPH_ID(fraghdr))));
- IPFRAG_STATS_INC(ip_frag.cachehit);
- break;
- }
- ipr_prev = ipr;
- }
-
- if (ipr == NULL) {
- /* Enqueue a new datagram into the datagram queue */
- ipr = ip_reass_enqueue_new_datagram(fraghdr, clen);
- /* Bail if unable to enqueue */
- if(ipr == NULL) {
- goto nullreturn;
- }
- } else {
- if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
- ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) {
- /* ipr->iphdr is not the header from the first fragment, but fraghdr is
- * -> copy fraghdr into ipr->iphdr since we want to have the header
- * of the first fragment (for ICMP time exceeded and later, for copying
- * all options, if supported)*/
- SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
- }
- }
- /* Track the current number of pbufs current 'in-flight', in order to limit
- the number of fragments that may be enqueued at any one time */
- ip_reass_pbufcount += clen;
-
- /* At this point, we have either created a new entry or pointing
- * to an existing one */
-
- /* check for 'no more fragments', and update queue entry*/
- if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
- ipr->flags |= IP_REASS_FLAG_LASTFRAG;
- ipr->datagram_len = offset + len;
- LWIP_DEBUGF(IP_REASS_DEBUG,
- ("ip_reass: last fragment seen, total len %"S16_F"\n",
- ipr->datagram_len));
- }
- /* find the right place to insert this pbuf */
- /* @todo: trim pbufs if fragments are overlapping */
- if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
- /* the totally last fragment (flag more fragments = 0) was received at least
- * once AND all fragments are received */
- ipr->datagram_len += IP_HLEN;
-
- /* save the second pbuf before copying the header over the pointer */
- r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf;
-
- /* copy the original ip header back to the first pbuf */
- fraghdr = (struct ip_hdr*)(ipr->p->payload);
- SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN);
- IPH_LEN_SET(fraghdr, htons(ipr->datagram_len));
- IPH_OFFSET_SET(fraghdr, 0);
- IPH_CHKSUM_SET(fraghdr, 0);
- /* @todo: do we need to set calculate the correct checksum? */
- IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
-
- p = ipr->p;
-
- /* chain together the pbufs contained within the reass_data list. */
- while(r != NULL) {
- iprh = (struct ip_reass_helper*)r->payload;
-
- /* hide the ip header for every succeding fragment */
- pbuf_header(r, -IP_HLEN);
- pbuf_cat(p, r);
- r = iprh->next_pbuf;
- }
- /* release the sources allocate for the fragment queue entry */
- ip_reass_dequeue_datagram(ipr, ipr_prev);
-
- /* and adjust the number of pbufs currently queued for reassembly. */
- ip_reass_pbufcount -= pbuf_clen(p);
-
- /* Return the pbuf chain */
- return p;
- }
- /* the datagram is not (yet?) reassembled completely */
- LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount));
- return NULL;
-
-nullreturn:
- LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n"));
- IPFRAG_STATS_INC(ip_frag.drop);
- pbuf_free(p);
- return NULL;
-}
-#endif /* IP_REASSEMBLY */
-
-#if IP_FRAG
-#if IP_FRAG_USES_STATIC_BUF
-static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
-#else /* IP_FRAG_USES_STATIC_BUF */
-
-#if !LWIP_NETIF_TX_SINGLE_PBUF
-/** Allocate a new struct pbuf_custom_ref */
-static struct pbuf_custom_ref*
-ip_frag_alloc_pbuf_custom_ref(void)
-{
- return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
-}
-
-/** Free a struct pbuf_custom_ref */
-static void
-ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
-{
- LWIP_ASSERT("p != NULL", p != NULL);
- memp_free(MEMP_FRAG_PBUF, p);
-}
-
-/** Free-callback function to free a 'struct pbuf_custom_ref', called by
- * pbuf_free. */
-static void
-ipfrag_free_pbuf_custom(struct pbuf *p)
-{
- struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
- LWIP_ASSERT("pcr != NULL", pcr != NULL);
- LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
- if (pcr->original != NULL) {
- pbuf_free(pcr->original);
- }
- ip_frag_free_pbuf_custom_ref(pcr);
-}
-#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
-#endif /* IP_FRAG_USES_STATIC_BUF */
-
-/**
- * Fragment an IP datagram if too large for the netif.
- *
- * Chop the datagram in MTU sized chunks and send them in order
- * by using a fixed size static memory buffer (PBUF_REF) or
- * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF).
- *
- * @param p ip packet to send
- * @param netif the netif on which to send
- * @param dest destination ip address to which to send
- *
- * @return ERR_OK if sent successfully, err_t otherwise
- */
-err_t
-ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest)
-{
- struct pbuf *rambuf;
-#if IP_FRAG_USES_STATIC_BUF
- struct pbuf *header;
-#else
-#if !LWIP_NETIF_TX_SINGLE_PBUF
- struct pbuf *newpbuf;
-#endif
- struct ip_hdr *original_iphdr;
-#endif
- struct ip_hdr *iphdr;
- u16_t nfb;
- u16_t left, cop;
- u16_t mtu = netif->mtu;
- u16_t ofo, omf;
- u16_t last;
- u16_t poff = IP_HLEN;
- u16_t tmp;
-#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
- u16_t newpbuflen = 0;
- u16_t left_to_copy;
-#endif
-
- /* Get a RAM based MTU sized pbuf */
-#if IP_FRAG_USES_STATIC_BUF
- /* When using a static buffer, we use a PBUF_REF, which we will
- * use to reference the packet (without link header).
- * Layer and length is irrelevant.
- */
- rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
- if (rambuf == NULL) {
- LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n"));
- return ERR_MEM;
- }
- rambuf->tot_len = rambuf->len = mtu;
- rambuf->payload = LWIP_MEM_ALIGN((void *)buf);
-
- /* Copy the IP header in it */
- iphdr = (struct ip_hdr *)rambuf->payload;
- SMEMCPY(iphdr, p->payload, IP_HLEN);
-#else /* IP_FRAG_USES_STATIC_BUF */
- original_iphdr = (struct ip_hdr *)p->payload;
- iphdr = original_iphdr;
-#endif /* IP_FRAG_USES_STATIC_BUF */
-
- /* Save original offset */
- tmp = ntohs(IPH_OFFSET(iphdr));
- ofo = tmp & IP_OFFMASK;
- omf = tmp & IP_MF;
-
- left = p->tot_len - IP_HLEN;
-
- nfb = (mtu - IP_HLEN) / 8;
-
- while (left) {
- last = (left <= mtu - IP_HLEN);
-
- /* Set new offset and MF flag */
- tmp = omf | (IP_OFFMASK & (ofo));
- if (!last) {
- tmp = tmp | IP_MF;
- }
-
- /* Fill this fragment */
- cop = last ? left : nfb * 8;
-
-#if IP_FRAG_USES_STATIC_BUF
- poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff);
-#else /* IP_FRAG_USES_STATIC_BUF */
-#if LWIP_NETIF_TX_SINGLE_PBUF
- rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM);
- if (rambuf == NULL) {
- return ERR_MEM;
- }
- LWIP_ASSERT("this needs a pbuf in one piece!",
- (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
- poff += pbuf_copy_partial(p, rambuf->payload, cop, poff);
- /* make room for the IP header */
- if(pbuf_header(rambuf, IP_HLEN)) {
- pbuf_free(rambuf);
- return ERR_MEM;
- }
- /* fill in the IP header */
- SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
- iphdr = rambuf->payload;
-#else /* LWIP_NETIF_TX_SINGLE_PBUF */
- /* When not using a static buffer, create a chain of pbufs.
- * The first will be a PBUF_RAM holding the link and IP header.
- * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
- * but limited to the size of an mtu.
- */
- rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM);
- if (rambuf == NULL) {
- return ERR_MEM;
- }
- LWIP_ASSERT("this needs a pbuf in one piece!",
- (p->len >= (IP_HLEN)));
- SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
- iphdr = (struct ip_hdr *)rambuf->payload;
-
- /* Can just adjust p directly for needed offset. */
- p->payload = (u8_t *)p->payload + poff;
- p->len -= poff;
-
- left_to_copy = cop;
- while (left_to_copy) {
- struct pbuf_custom_ref *pcr;
- newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
- /* Is this pbuf already empty? */
- if (!newpbuflen) {
- p = p->next;
- continue;
- }
- pcr = ip_frag_alloc_pbuf_custom_ref();
- if (pcr == NULL) {
- pbuf_free(rambuf);
- return ERR_MEM;
- }
- /* Mirror this pbuf, although we might not need all of it. */
- newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
- if (newpbuf == NULL) {
- ip_frag_free_pbuf_custom_ref(pcr);
- pbuf_free(rambuf);
- return ERR_MEM;
- }
- pbuf_ref(p);
- pcr->original = p;
- pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
-
- /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
- * so that it is removed when pbuf_dechain is later called on rambuf.
- */
- pbuf_cat(rambuf, newpbuf);
- left_to_copy -= newpbuflen;
- if (left_to_copy) {
- p = p->next;
- }
- }
- poff = newpbuflen;
-#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
-#endif /* IP_FRAG_USES_STATIC_BUF */
-
- /* Correct header */
- IPH_OFFSET_SET(iphdr, htons(tmp));
- IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
- IPH_CHKSUM_SET(iphdr, 0);
- IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
-
-#if IP_FRAG_USES_STATIC_BUF
- if (last) {
- pbuf_realloc(rambuf, left + IP_HLEN);
- }
-
- /* This part is ugly: we alloc a RAM based pbuf for
- * the link level header for each chunk and then
- * free it.A PBUF_ROM style pbuf for which pbuf_header
- * worked would make things simpler.
- */
- header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
- if (header != NULL) {
- pbuf_chain(header, rambuf);
- netif->output(netif, header, dest);
- IPFRAG_STATS_INC(ip_frag.xmit);
- snmp_inc_ipfragcreates();
- pbuf_free(header);
- } else {
- LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n"));
- pbuf_free(rambuf);
- return ERR_MEM;
- }
-#else /* IP_FRAG_USES_STATIC_BUF */
- /* No need for separate header pbuf - we allowed room for it in rambuf
- * when allocated.
- */
- netif->output(netif, rambuf, dest);
- IPFRAG_STATS_INC(ip_frag.xmit);
-
- /* Unfortunately we can't reuse rambuf - the hardware may still be
- * using the buffer. Instead we free it (and the ensuing chain) and
- * recreate it next time round the loop. If we're lucky the hardware
- * will have already sent the packet, the free will really free, and
- * there will be zero memory penalty.
- */
-
- pbuf_free(rambuf);
-#endif /* IP_FRAG_USES_STATIC_BUF */
- left -= cop;
- ofo += nfb;
- }
-#if IP_FRAG_USES_STATIC_BUF
- pbuf_free(rambuf);
-#endif /* IP_FRAG_USES_STATIC_BUF */
- snmp_inc_ipfragoks();
- return ERR_OK;
-}
-#endif /* IP_FRAG */