Merge branch 'feature/sync_lwip_as_submodule' into 'master'
Feature/sync lwip as submodule See merge request idf/esp-idf!2685
This commit is contained in:
commit
b999d10e8c
209 changed files with 81 additions and 84047 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -49,3 +49,7 @@
|
||||||
[submodule "components/expat/expat"]
|
[submodule "components/expat/expat"]
|
||||||
path = components/expat/expat
|
path = components/expat/expat
|
||||||
url = https://github.com/libexpat/libexpat.git
|
url = https://github.com/libexpat/libexpat.git
|
||||||
|
|
||||||
|
[submodule "components/lwip/lwip"]
|
||||||
|
path = components/lwip/lwip
|
||||||
|
url = https://github.com/espressif/esp-lwip.git
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#if __has_include("soc/soc.h")
|
#if __has_include("soc/soc.h")
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if __has_include("apps/ping/esp_ping.h")
|
||||||
|
#include "apps/ping/esp_ping.h"
|
||||||
|
#endif
|
||||||
#if __has_include("esp32/ulp.h")
|
#if __has_include("esp32/ulp.h")
|
||||||
#include "esp32/ulp.h"
|
#include "esp32/ulp.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,9 +28,6 @@
|
||||||
#if __has_include("esp_ota_ops.h")
|
#if __has_include("esp_ota_ops.h")
|
||||||
#include "esp_ota_ops.h"
|
#include "esp_ota_ops.h"
|
||||||
#endif
|
#endif
|
||||||
#if __has_include("esp_ping.h")
|
|
||||||
#include "esp_ping.h"
|
|
||||||
#endif
|
|
||||||
#if __has_include("esp_spi_flash.h")
|
#if __has_include("esp_spi_flash.h")
|
||||||
#include "esp_spi_flash.h"
|
#include "esp_spi_flash.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -399,7 +399,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||||
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED
|
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED
|
||||||
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED), /* 20487 0x5007 */
|
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED), /* 20487 0x5007 */
|
||||||
# endif
|
# endif
|
||||||
// components/lwip/apps/ping/esp_ping.h
|
// components/lwip/include/apps/ping/esp_ping.h
|
||||||
# ifdef ESP_ERR_PING_BASE
|
# ifdef ESP_ERR_PING_BASE
|
||||||
ERR_TBL_IT(ESP_ERR_PING_BASE), /* 24576 0x6000 */
|
ERR_TBL_IT(ESP_ERR_PING_BASE), /* 24576 0x6000 */
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -1138,7 +1138,6 @@ test cases:
|
||||||
- - R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+
|
- - R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+
|
||||||
- - SSC SSC1 soc -I
|
- - SSC SSC1 soc -I
|
||||||
- - P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ip>,<pc_ip>,<test_tcp_port1>)
|
- - P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ip>,<pc_ip>,<test_tcp_port1>)
|
||||||
- P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)
|
|
||||||
- P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)
|
- P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)
|
||||||
- P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ip>,<random_port>,<pc_ip>)
|
- P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ip>,<random_port>,<pc_ip>)
|
||||||
execution time: 0.0
|
execution time: 0.0
|
||||||
|
@ -1385,7 +1384,6 @@ test cases:
|
||||||
- - R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+
|
- - R SSC1 A <sock4>:ACCEPT:(\d+),\d+,.+,\d+
|
||||||
- - SSC SSC1 soc -I
|
- - SSC SSC1 soc -I
|
||||||
- - P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ap_ip>,<pc_ip_wifi>,<test_tcp_port1>)
|
- - P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(<sock1>,<target_ap_ip>,<pc_ip_wifi>,<test_tcp_port1>)
|
||||||
- P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%(<sock2>)
|
|
||||||
- P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)
|
- P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(<sock3>,<random_port>)
|
||||||
- P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ap_ip>,<random_port>,<pc_ip_wifi>)
|
- P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(<sock4>,<target_ap_ip>,<random_port>,<pc_ip_wifi>)
|
||||||
execution time: 0.0
|
execution time: 0.0
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2001, 2002 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
INTRODUCTION
|
|
||||||
|
|
||||||
lwIP is a small independent implementation of the TCP/IP protocol
|
|
||||||
suite that has been developed by Adam Dunkels at the Computer and
|
|
||||||
Networks Architectures (CNA) lab at the Swedish Institute of Computer
|
|
||||||
Science (SICS).
|
|
||||||
|
|
||||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
|
||||||
while still having a full scale TCP. This making lwIP suitable for use
|
|
||||||
in embedded systems with tens of kilobytes of free RAM and room for
|
|
||||||
around 40 kilobytes of code ROM.
|
|
||||||
|
|
||||||
FEATURES
|
|
||||||
|
|
||||||
* IP (Internet Protocol) including packet forwarding over multiple network
|
|
||||||
interfaces
|
|
||||||
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
|
|
||||||
* IGMP (Internet Group Management Protocol) for multicast traffic management
|
|
||||||
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
|
|
||||||
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
|
|
||||||
and fast recovery/fast retransmit
|
|
||||||
* Specialized raw/native API for enhanced performance
|
|
||||||
* Optional Berkeley-like socket API
|
|
||||||
* DNS (Domain names resolver)
|
|
||||||
* SNMP (Simple Network Management Protocol)
|
|
||||||
* DHCP (Dynamic Host Configuration Protocol)
|
|
||||||
* AUTOIP (for IPv4, conform with RFC 3927)
|
|
||||||
* PPP (Point-to-Point Protocol)
|
|
||||||
* ARP (Address Resolution Protocol) for Ethernet
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
|
|
||||||
lwIP is freely available under a BSD license.
|
|
||||||
|
|
||||||
DEVELOPMENT
|
|
||||||
|
|
||||||
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
|
||||||
and developers using the stack often submit bug fixes, improvements,
|
|
||||||
and additions to the stack to further increase its usefulness.
|
|
||||||
|
|
||||||
Development of lwIP is hosted on Savannah, a central point for
|
|
||||||
software development, maintenance and distribution. Everyone can
|
|
||||||
help improve lwIP by use of Savannah's interface, Git and the
|
|
||||||
mailing list. A core team of developers will commit changes to the
|
|
||||||
Git source tree.
|
|
||||||
|
|
||||||
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
|
|
||||||
contributions (such as platform ports) are in the 'contrib' Git module.
|
|
||||||
|
|
||||||
See doc/savannah.txt for details on Git server access for users and
|
|
||||||
developers.
|
|
||||||
|
|
||||||
The current Git trees are web-browsable:
|
|
||||||
http://git.savannah.gnu.org/cgit/lwip.git
|
|
||||||
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
|
|
||||||
|
|
||||||
Submit patches and bugs via the lwIP project page:
|
|
||||||
http://savannah.nongnu.org/projects/lwip/
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION
|
|
||||||
|
|
||||||
The original out-dated homepage of lwIP and Adam Dunkels' papers on
|
|
||||||
lwIP are at the official lwIP home page:
|
|
||||||
http://www.sics.se/~adam/lwip/
|
|
||||||
|
|
||||||
Self documentation of the source code is regularly extracted from the
|
|
||||||
current Git sources and is available from this web page:
|
|
||||||
http://www.nongnu.org/lwip/
|
|
||||||
|
|
||||||
There is now a constantly growin wiki about lwIP at
|
|
||||||
http://lwip.wikia.com/wiki/LwIP_Wiki
|
|
||||||
|
|
||||||
Also, there are mailing lists you can subscribe at
|
|
||||||
http://savannah.nongnu.org/mail/?group=lwip
|
|
||||||
plus searchable archives:
|
|
||||||
http://lists.nongnu.org/archive/html/lwip-users/
|
|
||||||
http://lists.nongnu.org/archive/html/lwip-devel/
|
|
||||||
|
|
||||||
Reading Adam's papers, the files in docs/, browsing the source code
|
|
||||||
documentation and browsing the mailing list archives is a good way to
|
|
||||||
become familiar with the design of lwIP.
|
|
||||||
|
|
||||||
Adam Dunkels <adam@sics.se>
|
|
||||||
Leon Woestenberg <leon.woestenberg@gmx.net>
|
|
||||||
|
|
|
@ -1,984 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Sequential API External module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the part of the API that is linked with
|
|
||||||
the application */
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/raw.h"
|
|
||||||
#include "lwip/udp.h"
|
|
||||||
#include "lwip/priv/api_msg.h"
|
|
||||||
#include "lwip/priv/tcp_priv.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define API_MSG_VAR_REF(name) API_VAR_REF(name)
|
|
||||||
#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name)
|
|
||||||
#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name)
|
|
||||||
#define API_MSG_VAR_ALLOC_DONTFAIL(name) API_VAR_ALLOC_DONTFAIL(struct api_msg, MEMP_API_MSG, name)
|
|
||||||
#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name)
|
|
||||||
|
|
||||||
static err_t netconn_close_shutdown(struct netconn *conn, u8_t how);
|
|
||||||
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
/**
|
|
||||||
* Call the lower part of a netconn_* function
|
|
||||||
* This function is then running in the thread context
|
|
||||||
* of tcpip_thread and has exclusive access to lwIP core code.
|
|
||||||
*
|
|
||||||
* @param apimsg a struct containing the function to call and its parameters
|
|
||||||
* @return ERR_OK if the function was called, another err_t if not
|
|
||||||
*/
|
|
||||||
static err_t ESP_IRAM_ATTR
|
|
||||||
tcpip_apimsg(struct api_msg *apimsg)
|
|
||||||
{
|
|
||||||
#if LWIP_DEBUG
|
|
||||||
/* catch functions that don't set err */
|
|
||||||
apimsg->msg.err = ERR_VAL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
|
|
||||||
LWIP_ASSERT("netconn semaphore not initialized",
|
|
||||||
sys_sem_valid(apimsg->msg.op_completed_sem));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tcpip_send_api_msg(apimsg->function, &apimsg->msg, LWIP_API_MSG_SEM(&apimsg->msg)) == ERR_OK) {
|
|
||||||
return apimsg->msg.err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new netconn (of a specific type) that has a callback function.
|
|
||||||
* The corresponding pcb is also created.
|
|
||||||
*
|
|
||||||
* @param t the type of 'connection' to create (@see enum netconn_type)
|
|
||||||
* @param proto the IP protocol for RAW IP pcbs
|
|
||||||
* @param callback a function to call on status changes (RX available, TX'ed)
|
|
||||||
* @return a newly allocated struct netconn or
|
|
||||||
* NULL on memory error
|
|
||||||
*/
|
|
||||||
struct netconn*
|
|
||||||
netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
|
|
||||||
{
|
|
||||||
struct netconn *conn;
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
|
|
||||||
conn = netconn_alloc(t, callback);
|
|
||||||
if (conn != NULL) {
|
|
||||||
err_t err;
|
|
||||||
API_MSG_VAR_ALLOC_DONTFAIL(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.n.proto = proto;
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
|
|
||||||
LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
|
|
||||||
#if LWIP_TCP
|
|
||||||
LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
|
|
||||||
sys_sem_free(&conn->op_completed);
|
|
||||||
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
sys_mbox_free(&conn->recvmbox);
|
|
||||||
memp_free(MEMP_NETCONN, conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_created_by_socket(struct netconn *conn)
|
|
||||||
{
|
|
||||||
#if LWIP_SOCKET
|
|
||||||
if (conn && (conn->socket >= 0)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Close a netconn 'connection' and free its resources.
|
|
||||||
* UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
|
|
||||||
* after this returns.
|
|
||||||
*
|
|
||||||
* @param conn the netconn to delete
|
|
||||||
* @return ERR_OK if the connection was deleted
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_delete(struct netconn *conn)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
|
|
||||||
/* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
|
|
||||||
if (conn == NULL) {
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
|
|
||||||
/* get the time we started, which is later compared to
|
|
||||||
sys_now() + conn->send_timeout */
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now();
|
|
||||||
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
#if LWIP_TCP
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.sd.polls_left =
|
|
||||||
((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_delconn, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ESP_THREAD_SAFE
|
|
||||||
if (is_created_by_socket(conn) == false) {
|
|
||||||
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("netconn_delete - free conn\n"));
|
|
||||||
netconn_free(conn);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("netconn_delete - free conn\n"));
|
|
||||||
netconn_free(conn);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the local or remote IP address and port of a netconn.
|
|
||||||
* For RAW netconns, this returns the protocol instead of a port!
|
|
||||||
*
|
|
||||||
* @param conn the netconn to query
|
|
||||||
* @param addr a pointer to which to save the IP address
|
|
||||||
* @param port a pointer to which to save the port (or protocol for RAW)
|
|
||||||
* @param local 1 to get the local IP address, 0 to get the remote one
|
|
||||||
* @return ERR_CONN for invalid connections
|
|
||||||
* ERR_OK if the information was retrieved
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.ad.local = local;
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err);
|
|
||||||
*addr = msg->msg.msg.ad.ipaddr;
|
|
||||||
*port = msg->msg.msg.ad.port;
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
msg.msg.msg.ad.ipaddr = addr;
|
|
||||||
msg.msg.msg.ad.port = port;
|
|
||||||
TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err);
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind a netconn to a specific local IP address and port.
|
|
||||||
* Binding one netconn twice might not always be checked correctly!
|
|
||||||
*
|
|
||||||
* @param conn the netconn to bind
|
|
||||||
* @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
|
|
||||||
* to bind to all addresses)
|
|
||||||
* @param port the local port to bind the netconn to (not used for RAW)
|
|
||||||
* @return ERR_OK if bound, any other err_t on failure
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
|
||||||
if (addr == NULL) {
|
|
||||||
addr = IP_ADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr);
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.bc.port = port;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_bind, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect a netconn to a specific remote IP address and port.
|
|
||||||
*
|
|
||||||
* @param conn the netconn to connect
|
|
||||||
* @param addr the remote IP address to connect to
|
|
||||||
* @param port the remote port to connect to (no used for RAW)
|
|
||||||
* @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
|
||||||
if (addr == NULL) {
|
|
||||||
addr = IP_ADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr);
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.bc.port = port;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_connect, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect a netconn from its current peer (only valid for UDP netconns).
|
|
||||||
*
|
|
||||||
* @param conn the netconn to disconnect
|
|
||||||
* @return TODO: return value is not set here...
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_disconnect(struct netconn *conn)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_disconnect, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a TCP netconn into listen mode
|
|
||||||
*
|
|
||||||
* @param conn the tcp netconn to set to listen mode
|
|
||||||
* @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
|
|
||||||
* @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
|
|
||||||
* don't return any error (yet?))
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
|
||||||
{
|
|
||||||
#if LWIP_TCP
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
/* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
|
|
||||||
LWIP_UNUSED_ARG(backlog);
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.lb.backlog = backlog;
|
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_listen, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
#else /* LWIP_TCP */
|
|
||||||
LWIP_UNUSED_ARG(conn);
|
|
||||||
LWIP_UNUSED_ARG(backlog);
|
|
||||||
return ERR_ARG;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accept a new connection on a TCP listening netconn.
|
|
||||||
*
|
|
||||||
* @param conn the TCP listen netconn
|
|
||||||
* @param new_conn pointer where the new connection is stored
|
|
||||||
* @return ERR_OK if a new connection has been received or an error
|
|
||||||
* code otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|
||||||
{
|
|
||||||
#if LWIP_TCP
|
|
||||||
struct netconn *newconn;
|
|
||||||
err_t err;
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
|
|
||||||
*new_conn = NULL;
|
|
||||||
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
|
|
||||||
|
|
||||||
err = conn->last_err;
|
|
||||||
if (ERR_IS_FATAL(err)) {
|
|
||||||
/* don't recv on fatal errors: this might block the application task
|
|
||||||
waiting on acceptmbox forever! */
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_SO_RCVTIMEO
|
|
||||||
if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
|
|
||||||
return ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
|
|
||||||
#endif /* LWIP_SO_RCVTIMEO*/
|
|
||||||
/* Register event with callback */
|
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
|
||||||
|
|
||||||
if (newconn == NULL) {
|
|
||||||
/* connection has been aborted */
|
|
||||||
/* in this special case, we set the netconn error from application thread, as
|
|
||||||
on a ready-to-accept listening netconn, there should not be anything running
|
|
||||||
in tcpip_thread */
|
|
||||||
NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
|
|
||||||
return ERR_ABRT;
|
|
||||||
}
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
|
||||||
/* Let the stack know that we have accepted the connection. */
|
|
||||||
API_MSG_VAR_ALLOC_DONTFAIL(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = newconn;
|
|
||||||
/* don't care for the return value of lwip_netconn_do_accepted */
|
|
||||||
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_accepted);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
|
||||||
|
|
||||||
*new_conn = newconn;
|
|
||||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
|
||||||
return ERR_OK;
|
|
||||||
#else /* LWIP_TCP */
|
|
||||||
LWIP_UNUSED_ARG(conn);
|
|
||||||
LWIP_UNUSED_ARG(new_conn);
|
|
||||||
return ERR_ARG;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data: actual implementation that doesn't care whether pbuf or netbuf
|
|
||||||
* is received
|
|
||||||
*
|
|
||||||
* @param conn the netconn from which to receive data
|
|
||||||
* @param new_buf pointer where a new pbuf/netbuf is stored when received data
|
|
||||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
|
||||||
* memory error or another error)
|
|
||||||
*/
|
|
||||||
static err_t ESP_IRAM_ATTR
|
|
||||||
netconn_recv_data(struct netconn *conn, void **new_buf)
|
|
||||||
{
|
|
||||||
void *buf = NULL;
|
|
||||||
u16_t len;
|
|
||||||
err_t err;
|
|
||||||
#if LWIP_TCP
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
|
|
||||||
*new_buf = NULL;
|
|
||||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
#if LWIP_TCP
|
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
|
||||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
|
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
|
||||||
{
|
|
||||||
if (!sys_mbox_valid(&conn->recvmbox)) {
|
|
||||||
/* This happens when calling this function after receiving FIN */
|
|
||||||
return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
|
||||||
|
|
||||||
err = conn->last_err;
|
|
||||||
if (ERR_IS_FATAL(err)) {
|
|
||||||
/* don't recv on fatal errors: this might block the application task
|
|
||||||
waiting on recvmbox forever! */
|
|
||||||
/* @todo: this does not allow us to fetch data that has been put into recvmbox
|
|
||||||
before the fatal error occurred - is that a problem? */
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_SO_RCVTIMEO
|
|
||||||
if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
|
|
||||||
return ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
|
|
||||||
#endif /* LWIP_SO_RCVTIMEO*/
|
|
||||||
|
|
||||||
#if LWIP_TCP
|
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
|
||||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
|
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
|
||||||
{
|
|
||||||
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
|
|
||||||
/* Let the stack know that we have taken the data. */
|
|
||||||
/* TODO: Speedup: Don't block and wait for the answer here
|
|
||||||
(to prevent multiple thread-switches). */
|
|
||||||
API_MSG_VAR_ALLOC_DONTFAIL(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
if (buf != NULL) {
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
|
|
||||||
} else {
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.r.len = 1;
|
|
||||||
}
|
|
||||||
/* don't care for the return value of lwip_netconn_do_recv */
|
|
||||||
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are closed, we indicate that we no longer wish to use the socket */
|
|
||||||
if (buf == NULL) {
|
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
|
||||||
/* Don' store ERR_CLSD as conn->err since we are only half-closed */
|
|
||||||
return ERR_CLSD;
|
|
||||||
}
|
|
||||||
len = ((struct pbuf *)buf)->tot_len;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
|
|
||||||
else
|
|
||||||
#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
|
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
|
||||||
{
|
|
||||||
#if ESP_THREAD_SAFE
|
|
||||||
if (buf == NULL){
|
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
|
||||||
return ERR_CLSD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
LWIP_ASSERT("buf != NULL", buf != NULL);
|
|
||||||
len = netbuf_len((struct netbuf *)buf);
|
|
||||||
}
|
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
|
||||||
|
|
||||||
#if ESP_PERF
|
|
||||||
if (len > DBG_PERF_FILTER_LEN) {
|
|
||||||
DBG_PERF_PATH_SET(DBG_PERF_DIR_RX, DBG_PERF_POINT_SOC_IN);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_SO_RCVBUF
|
|
||||||
SYS_ARCH_DEC(conn->recv_avail, len);
|
|
||||||
#endif /* LWIP_SO_RCVBUF */
|
|
||||||
/* Register event with callback */
|
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
|
|
||||||
|
|
||||||
*new_buf = buf;
|
|
||||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data (in form of a pbuf) from a TCP netconn
|
|
||||||
*
|
|
||||||
* @param conn the netconn from which to receive data
|
|
||||||
* @param new_buf pointer where a new pbuf is stored when received data
|
|
||||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
|
||||||
* memory error or another error)
|
|
||||||
* ERR_ARG if conn is not a TCP netconn
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
|
|
||||||
NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
|
|
||||||
|
|
||||||
return netconn_recv_data(conn, (void **)new_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data (in form of a netbuf containing a packet buffer) from a netconn
|
|
||||||
*
|
|
||||||
* @param conn the netconn from which to receive data
|
|
||||||
* @param new_buf pointer where a new netbuf is stored when received data
|
|
||||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
|
||||||
* memory error or another error)
|
|
||||||
*/
|
|
||||||
err_t ESP_IRAM_ATTR
|
|
||||||
netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
|
||||||
{
|
|
||||||
#if LWIP_TCP
|
|
||||||
struct netbuf *buf = NULL;
|
|
||||||
err_t err;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
|
|
||||||
*new_buf = NULL;
|
|
||||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
#if LWIP_TCP
|
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
|
||||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
|
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
|
||||||
{
|
|
||||||
struct pbuf *p = NULL;
|
|
||||||
/* This is not a listening netconn, since recvmbox is set */
|
|
||||||
|
|
||||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
|
||||||
if (buf == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = netconn_recv_data(conn, (void **)&p);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
memp_free(MEMP_NETBUF, buf);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("p != NULL", p != NULL);
|
|
||||||
|
|
||||||
buf->p = p;
|
|
||||||
buf->ptr = p;
|
|
||||||
buf->port = 0;
|
|
||||||
ip_addr_set_zero(&buf->addr);
|
|
||||||
*new_buf = buf;
|
|
||||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
|
|
||||||
else
|
|
||||||
#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
|
|
||||||
{
|
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
|
||||||
return netconn_recv_data(conn, (void **)new_buf);
|
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP: update the receive window: by calling this, the application
|
|
||||||
* tells the stack that it has processed data and is able to accept
|
|
||||||
* new data.
|
|
||||||
* ATTENTION: use with care, this is mainly used for sockets!
|
|
||||||
* Can only be used when calling netconn_set_noautorecved(conn, 1) before.
|
|
||||||
*
|
|
||||||
* @param conn the netconn for which to update the receive window
|
|
||||||
* @param length amount of data processed (ATTENTION: this must be accurate!)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
netconn_recved(struct netconn *conn, u32_t length)
|
|
||||||
{
|
|
||||||
#if LWIP_TCP
|
|
||||||
if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) &&
|
|
||||||
(netconn_get_noautorecved(conn))) {
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
/* Let the stack know that we have taken the data. */
|
|
||||||
/* TODO: Speedup: Don't block and wait for the answer here
|
|
||||||
(to prevent multiple thread-switches). */
|
|
||||||
API_MSG_VAR_ALLOC_DONTFAIL(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.r.len = length;
|
|
||||||
/* don't care for the return value of lwip_netconn_do_recv */
|
|
||||||
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
}
|
|
||||||
#else /* LWIP_TCP */
|
|
||||||
LWIP_UNUSED_ARG(conn);
|
|
||||||
LWIP_UNUSED_ARG(length);
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send data (in form of a netbuf) to a specific remote IP address and port.
|
|
||||||
* Only to be used for UDP and RAW netconns (not TCP).
|
|
||||||
*
|
|
||||||
* @param conn the netconn over which to send data
|
|
||||||
* @param buf a netbuf containing the data to send
|
|
||||||
* @param addr the remote IP address to which to send the data
|
|
||||||
* @param port the remote port to which to send the data
|
|
||||||
* @return ERR_OK if data was sent, any other err_t on error
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port)
|
|
||||||
{
|
|
||||||
if (buf != NULL) {
|
|
||||||
ip_addr_set(&buf->addr, addr);
|
|
||||||
buf->port = port;
|
|
||||||
return netconn_send(conn, buf);
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send data over a UDP or RAW netconn (that is already connected).
|
|
||||||
*
|
|
||||||
* @param conn the UDP or RAW netconn over which to send data
|
|
||||||
* @param buf a netbuf containing the data to send
|
|
||||||
* @return ERR_OK if data was sent, any other err_t on error
|
|
||||||
*/
|
|
||||||
err_t ESP_IRAM_ATTR
|
|
||||||
netconn_send(struct netconn *conn, struct netbuf *buf)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.b = buf;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_send, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send data over a TCP netconn.
|
|
||||||
*
|
|
||||||
* @param conn the TCP netconn over which to send data
|
|
||||||
* @param dataptr pointer to the application buffer that contains the data to send
|
|
||||||
* @param size size of the application data to send
|
|
||||||
* @param apiflags combination of following flags :
|
|
||||||
* - NETCONN_COPY: data will be copied into memory belonging to the stack
|
|
||||||
* - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
|
|
||||||
* - NETCONN_DONTBLOCK: only write the data if all data can be written at once
|
|
||||||
* @param bytes_written pointer to a location that receives the number of written bytes
|
|
||||||
* @return ERR_OK if data was sent, any other err_t on error
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|
||||||
u8_t apiflags, size_t *bytes_written)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
u8_t dontblock;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
|
|
||||||
if (size == 0) {
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
|
||||||
|
|
||||||
if (dontblock && !bytes_written) {
|
|
||||||
/* This implies netconn_write() cannot be used for non-blocking send, since
|
|
||||||
it has no way to return the number of bytes written. */
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
/* non-blocking write sends as much */
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.w.dataptr = dataptr;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.w.apiflags = apiflags;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.w.len = size;
|
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
if (conn->send_timeout != 0) {
|
|
||||||
/* get the time we started, which is later compared to
|
|
||||||
sys_now() + conn->send_timeout */
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.w.time_started = sys_now();
|
|
||||||
} else {
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.w.time_started = 0;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO */
|
|
||||||
|
|
||||||
/* For locking the core: this _can_ be delayed on low memory/low send buffer,
|
|
||||||
but if it is, this is done inside api_msg.c:do_write(), so we can use the
|
|
||||||
non-blocking version here. */
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_write, err);
|
|
||||||
if ((err == ERR_OK) && (bytes_written != NULL)) {
|
|
||||||
if (dontblock
|
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
|| (conn->send_timeout != 0)
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO */
|
|
||||||
) {
|
|
||||||
/* nonblocking write: maybe the data has been sent partly */
|
|
||||||
*bytes_written = API_MSG_VAR_REF(msg).msg.msg.w.len;
|
|
||||||
} else {
|
|
||||||
/* blocking call succeeded: all data has been sent if it */
|
|
||||||
*bytes_written = size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close or shutdown a TCP netconn (doesn't delete it).
|
|
||||||
*
|
|
||||||
* @param conn the TCP netconn to close or shutdown
|
|
||||||
* @param how fully close or only shutdown one side?
|
|
||||||
* @return ERR_OK if the netconn was closed, any other err_t on error
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
netconn_close_shutdown(struct netconn *conn, u8_t how)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
LWIP_UNUSED_ARG(how);
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
#if LWIP_TCP
|
|
||||||
/* shutting down both ends is the same as closing */
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.sd.shut = how;
|
|
||||||
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
|
|
||||||
/* get the time we started, which is later compared to
|
|
||||||
sys_now() + conn->send_timeout */
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now();
|
|
||||||
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.sd.polls_left =
|
|
||||||
((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_close, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close a TCP netconn (doesn't delete it).
|
|
||||||
*
|
|
||||||
* @param conn the TCP netconn to close
|
|
||||||
* @return ERR_OK if the netconn was closed, any other err_t on error
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_close(struct netconn *conn)
|
|
||||||
{
|
|
||||||
/* shutting down both ends is the same as closing */
|
|
||||||
return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shut down one or both sides of a TCP netconn (doesn't delete it).
|
|
||||||
*
|
|
||||||
* @param conn the TCP netconn to shut down
|
|
||||||
* @return ERR_OK if the netconn was closed, any other err_t on error
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
|
|
||||||
{
|
|
||||||
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
|
||||||
/**
|
|
||||||
* Join multicast groups for UDP netconns.
|
|
||||||
*
|
|
||||||
* @param conn the UDP netconn for which to change multicast addresses
|
|
||||||
* @param multiaddr IP address of the multicast group to join or leave
|
|
||||||
* @param netif_addr the IP address of the network interface on which to send
|
|
||||||
* the igmp message
|
|
||||||
* @param join_or_leave flag whether to send a join- or leave-message
|
|
||||||
* @return ERR_OK if the action was taken, any err_t on error
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netconn_join_leave_group(struct netconn *conn,
|
|
||||||
const ip_addr_t *multiaddr,
|
|
||||||
const ip_addr_t *netif_addr,
|
|
||||||
enum netconn_igmp join_or_leave)
|
|
||||||
{
|
|
||||||
API_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
|
||||||
|
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
|
||||||
if (multiaddr == NULL) {
|
|
||||||
multiaddr = IP_ADDR_ANY;
|
|
||||||
}
|
|
||||||
if (netif_addr == NULL) {
|
|
||||||
netif_addr = IP_ADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr);
|
|
||||||
API_MSG_VAR_REF(msg).msg.msg.jl.join_or_leave = join_or_leave;
|
|
||||||
TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_join_leave_group, err);
|
|
||||||
API_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
|
||||||
|
|
||||||
#if LWIP_DNS
|
|
||||||
/**
|
|
||||||
* Execute a DNS query, only one IP address is returned
|
|
||||||
*
|
|
||||||
* @param name a string representation of the DNS host name to query
|
|
||||||
* @param addr a preallocated ip_addr_t where to store the resolved IP address
|
|
||||||
* @return ERR_OK: resolving succeeded
|
|
||||||
* ERR_MEM: memory error, try again later
|
|
||||||
* ERR_ARG: dns client not initialized or invalid hostname
|
|
||||||
* ERR_VAL: dns server response was invalid
|
|
||||||
*/
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
err_t
|
|
||||||
netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
|
|
||||||
#else
|
|
||||||
err_t
|
|
||||||
netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
|
|
||||||
API_VAR_DECLARE(struct dns_api_msg, msg);
|
|
||||||
err_t localerr;
|
|
||||||
#if !LWIP_MPU_COMPATIBLE
|
|
||||||
sys_sem_t sem;
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
err_t err = ERR_OK;
|
|
||||||
|
|
||||||
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
if (strlen(name) >= DNS_MAX_NAME_LENGTH) {
|
|
||||||
return ERR_ARG;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg);
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1);
|
|
||||||
API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0;
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
msg.err = &err;
|
|
||||||
msg.sem = &sem;
|
|
||||||
API_VAR_REF(msg).addr = API_VAR_REF(addr);
|
|
||||||
API_VAR_REF(msg).name = name;
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
API_VAR_REF(msg).dns_addrtype = dns_addrtype;
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET();
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD*/
|
|
||||||
err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
localerr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
|
|
||||||
if (localerr != ERR_OK) {
|
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
|
|
||||||
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
|
|
||||||
return localerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
|
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
|
|
||||||
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
*addr = msg->addr;
|
|
||||||
err = msg->err;
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
|
|
||||||
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_DNS*/
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
void
|
|
||||||
netconn_thread_init(void)
|
|
||||||
{
|
|
||||||
sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
|
|
||||||
if ((sem == NULL) || !sys_sem_valid(sem)) {
|
|
||||||
/* call alloc only once */
|
|
||||||
LWIP_NETCONN_THREAD_SEM_ALLOC();
|
|
||||||
LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
netconn_thread_cleanup(void)
|
|
||||||
{
|
|
||||||
sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
|
|
||||||
if ((sem != NULL) && sys_sem_valid(sem)) {
|
|
||||||
/* call free only once */
|
|
||||||
LWIP_NETCONN_THREAD_SEM_FREE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Error Management module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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/err.h"
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
|
|
||||||
static const char *err_strerr[] = {
|
|
||||||
"Ok.", /* ERR_OK 0 */
|
|
||||||
"Out of memory error.", /* ERR_MEM -1 */
|
|
||||||
"Buffer error.", /* ERR_BUF -2 */
|
|
||||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
|
||||||
"Routing problem.", /* ERR_RTE -4 */
|
|
||||||
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
|
||||||
"Illegal value.", /* ERR_VAL -6 */
|
|
||||||
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
|
||||||
"Address in use.", /* ERR_USE -8 */
|
|
||||||
"Already connecting.", /* ERR_ALREADY -9 */
|
|
||||||
"Already connected.", /* ERR_ISCONN -10 */
|
|
||||||
"Not connected.", /* ERR_CONN -11 */
|
|
||||||
"Low-level netif error.", /* ERR_IF -12 */
|
|
||||||
"Connection aborted.", /* ERR_ABRT -13 */
|
|
||||||
"Connection reset.", /* ERR_RST -14 */
|
|
||||||
"Connection closed.", /* ERR_CLSD -15 */
|
|
||||||
"Illegal argument." /* ERR_ARG -16 */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an lwip internal error to a string representation.
|
|
||||||
*
|
|
||||||
* @param err an lwip internal err_t
|
|
||||||
* @return a string representation for err
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
lwip_strerr(err_t err)
|
|
||||||
{
|
|
||||||
return err_strerr[-err];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
|
@ -1,245 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Network buffer management
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/netbuf.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create (allocate) and initialize a new netbuf.
|
|
||||||
* The netbuf doesn't yet contain a packet buffer!
|
|
||||||
*
|
|
||||||
* @return a pointer to a new netbuf
|
|
||||||
* NULL on lack of memory
|
|
||||||
*/
|
|
||||||
struct
|
|
||||||
netbuf *netbuf_new(void)
|
|
||||||
{
|
|
||||||
struct netbuf *buf;
|
|
||||||
|
|
||||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
|
||||||
if (buf != NULL) {
|
|
||||||
buf->p = NULL;
|
|
||||||
buf->ptr = NULL;
|
|
||||||
ip_addr_set_zero(&buf->addr);
|
|
||||||
buf->port = 0;
|
|
||||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
buf->flags = 0;
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
buf->toport_chksum = 0;
|
|
||||||
#if LWIP_NETBUF_RECVINFO
|
|
||||||
ip_addr_set_zero(&buf->toaddr);
|
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
|
||||||
return buf;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deallocate a netbuf allocated by netbuf_new().
|
|
||||||
*
|
|
||||||
* @param buf pointer to a netbuf allocated by netbuf_new()
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
netbuf_delete(struct netbuf *buf)
|
|
||||||
{
|
|
||||||
if (buf != NULL) {
|
|
||||||
if (buf->p != NULL) {
|
|
||||||
pbuf_free(buf->p);
|
|
||||||
buf->p = buf->ptr = NULL;
|
|
||||||
}
|
|
||||||
memp_free(MEMP_NETBUF, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate memory for a packet buffer for a given netbuf.
|
|
||||||
*
|
|
||||||
* @param buf the netbuf for which to allocate a packet buffer
|
|
||||||
* @param size the size of the packet buffer to allocate
|
|
||||||
* @return pointer to the allocated memory
|
|
||||||
* NULL if no memory could be allocated
|
|
||||||
*/
|
|
||||||
void * ESP_IRAM_ATTR
|
|
||||||
netbuf_alloc(struct netbuf *buf, u16_t size)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
|
|
||||||
|
|
||||||
/* Deallocate any previously allocated memory. */
|
|
||||||
if (buf->p != NULL) {
|
|
||||||
pbuf_free(buf->p);
|
|
||||||
}
|
|
||||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
|
||||||
if (buf->p == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("check that first pbuf can hold size",
|
|
||||||
(buf->p->len >= size));
|
|
||||||
buf->ptr = buf->p;
|
|
||||||
return buf->p->payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the packet buffer included in a netbuf
|
|
||||||
*
|
|
||||||
* @param buf pointer to the netbuf which contains the packet buffer to free
|
|
||||||
*/
|
|
||||||
void ESP_IRAM_ATTR
|
|
||||||
netbuf_free(struct netbuf *buf)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
|
||||||
if (buf->p != NULL) {
|
|
||||||
pbuf_free(buf->p);
|
|
||||||
}
|
|
||||||
buf->p = buf->ptr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Let a netbuf reference existing (non-volatile) data.
|
|
||||||
*
|
|
||||||
* @param buf netbuf which should reference the data
|
|
||||||
* @param dataptr pointer to the data to reference
|
|
||||||
* @param size size of the data
|
|
||||||
* @return ERR_OK if data is referenced
|
|
||||||
* ERR_MEM if data couldn't be referenced due to lack of memory
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
|
|
||||||
if (buf->p != NULL) {
|
|
||||||
pbuf_free(buf->p);
|
|
||||||
}
|
|
||||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
|
||||||
if (buf->p == NULL) {
|
|
||||||
buf->ptr = NULL;
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
((struct pbuf_rom*)buf->p)->payload = dataptr;
|
|
||||||
buf->p->len = buf->p->tot_len = size;
|
|
||||||
buf->ptr = buf->p;
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chain one netbuf to another (@see pbuf_chain)
|
|
||||||
*
|
|
||||||
* @param head the first netbuf
|
|
||||||
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
|
|
||||||
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
|
||||||
pbuf_cat(head->p, tail->p);
|
|
||||||
head->ptr = head->p;
|
|
||||||
memp_free(MEMP_NETBUF, tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the data pointer and length of the data inside a netbuf.
|
|
||||||
*
|
|
||||||
* @param buf netbuf to get the data from
|
|
||||||
* @param dataptr pointer to a void pointer where to store the data pointer
|
|
||||||
* @param len pointer to an u16_t where the length of the data is stored
|
|
||||||
* @return ERR_OK if the information was retrieved,
|
|
||||||
* ERR_BUF on error.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
|
|
||||||
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
|
|
||||||
|
|
||||||
if (buf->ptr == NULL) {
|
|
||||||
return ERR_BUF;
|
|
||||||
}
|
|
||||||
*dataptr = buf->ptr->payload;
|
|
||||||
*len = buf->ptr->len;
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
|
||||||
* to the next part.
|
|
||||||
* The packet buffer itself is not modified.
|
|
||||||
*
|
|
||||||
* @param buf the netbuf to modify
|
|
||||||
* @return -1 if there is no next part
|
|
||||||
* 1 if moved to the next part but now there is no next part
|
|
||||||
* 0 if moved to the next part and there are still more parts
|
|
||||||
*/
|
|
||||||
s8_t
|
|
||||||
netbuf_next(struct netbuf *buf)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;);
|
|
||||||
if (buf->ptr->next == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buf->ptr = buf->ptr->next;
|
|
||||||
if (buf->ptr->next == NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
|
||||||
* to the beginning of the packet.
|
|
||||||
* The packet buffer itself is not modified.
|
|
||||||
*
|
|
||||||
* @param buf the netbuf to modify
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
netbuf_first(struct netbuf *buf)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
|
||||||
buf->ptr = buf->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN */
|
|
|
@ -1,421 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* API functions for name resolving
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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: Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/netdb.h"
|
|
||||||
|
|
||||||
#if LWIP_DNS && LWIP_SOCKET
|
|
||||||
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
|
||||||
struct gethostbyname_r_helper {
|
|
||||||
ip_addr_t *addr_list[2];
|
|
||||||
ip_addr_t addr;
|
|
||||||
char *aliases;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** h_errno is exported in netdb.h for access by applications. */
|
|
||||||
#if LWIP_DNS_API_DECLARE_H_ERRNO
|
|
||||||
int h_errno;
|
|
||||||
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
|
|
||||||
|
|
||||||
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
|
|
||||||
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
|
|
||||||
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
|
|
||||||
#define LWIP_DNS_API_HOSTENT_STORAGE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** define "hostent" variables storage */
|
|
||||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
|
||||||
#define HOSTENT_STORAGE
|
|
||||||
#else
|
|
||||||
#define HOSTENT_STORAGE static
|
|
||||||
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an entry containing addresses of address family AF_INET
|
|
||||||
* for the host with name name.
|
|
||||||
* Due to dns_gethostbyname limitations, only one address is returned.
|
|
||||||
*
|
|
||||||
* @param name the hostname to resolve
|
|
||||||
* @return an entry containing addresses of address family AF_INET
|
|
||||||
* for the host with name name
|
|
||||||
*/
|
|
||||||
struct hostent*
|
|
||||||
lwip_gethostbyname(const char *name)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
ip_addr_t addr;
|
|
||||||
|
|
||||||
/* buffer variables for lwip_gethostbyname() */
|
|
||||||
HOSTENT_STORAGE struct hostent s_hostent;
|
|
||||||
HOSTENT_STORAGE char *s_aliases;
|
|
||||||
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
|
|
||||||
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
|
|
||||||
HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
|
|
||||||
|
|
||||||
/* query host IP address */
|
|
||||||
err = netconn_gethostbyname(name, &addr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
|
||||||
h_errno = HOST_NOT_FOUND;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill hostent */
|
|
||||||
s_hostent_addr = addr;
|
|
||||||
s_phostent_addr[0] = &s_hostent_addr;
|
|
||||||
s_phostent_addr[1] = NULL;
|
|
||||||
strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
|
|
||||||
s_hostname[DNS_MAX_NAME_LENGTH] = 0;
|
|
||||||
s_hostent.h_name = s_hostname;
|
|
||||||
s_aliases = NULL;
|
|
||||||
s_hostent.h_aliases = &s_aliases;
|
|
||||||
s_hostent.h_addrtype = AF_INET;
|
|
||||||
s_hostent.h_length = sizeof(ip_addr_t);
|
|
||||||
s_hostent.h_addr_list = (char**)&s_phostent_addr;
|
|
||||||
|
|
||||||
#if DNS_DEBUG
|
|
||||||
/* dump hostent */
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases));
|
|
||||||
/* h_aliases are always empty */
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list));
|
|
||||||
if (s_hostent.h_addr_list != NULL) {
|
|
||||||
u8_t idx;
|
|
||||||
for (idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* DNS_DEBUG */
|
|
||||||
|
|
||||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
|
||||||
/* this function should return the "per-thread" hostent after copy from s_hostent */
|
|
||||||
return sys_thread_hostent(&s_hostent);
|
|
||||||
#else
|
|
||||||
return &s_hostent;
|
|
||||||
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thread-safe variant of lwip_gethostbyname: instead of using a static
|
|
||||||
* buffer, this function takes buffer and errno pointers as arguments
|
|
||||||
* and uses these for the result.
|
|
||||||
*
|
|
||||||
* @param name the hostname to resolve
|
|
||||||
* @param ret pre-allocated struct where to store the result
|
|
||||||
* @param buf pre-allocated buffer where to store additional data
|
|
||||||
* @param buflen the size of buf
|
|
||||||
* @param result pointer to a hostent pointer that is set to ret on success
|
|
||||||
* and set to zero on error
|
|
||||||
* @param h_errnop pointer to an int where to store errors (instead of modifying
|
|
||||||
* the global h_errno)
|
|
||||||
* @return 0 on success, non-zero on error, additional error information
|
|
||||||
* is stored in *h_errnop instead of h_errno to be thread-safe
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
|
||||||
size_t buflen, struct hostent **result, int *h_errnop)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
struct gethostbyname_r_helper *h;
|
|
||||||
char *hostname;
|
|
||||||
size_t namelen;
|
|
||||||
int lh_errno;
|
|
||||||
|
|
||||||
if (h_errnop == NULL) {
|
|
||||||
/* ensure h_errnop is never NULL */
|
|
||||||
h_errnop = &lh_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == NULL) {
|
|
||||||
/* not all arguments given */
|
|
||||||
*h_errnop = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* first thing to do: set *result to nothing */
|
|
||||||
*result = NULL;
|
|
||||||
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
|
|
||||||
/* not all arguments given */
|
|
||||||
*h_errnop = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
namelen = strlen(name);
|
|
||||||
if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
|
|
||||||
/* buf can't hold the data needed + a copy of name */
|
|
||||||
*h_errnop = ERANGE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
|
|
||||||
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
|
|
||||||
|
|
||||||
/* query host IP address */
|
|
||||||
err = netconn_gethostbyname(name, &h->addr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
|
||||||
*h_errnop = HOST_NOT_FOUND;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the hostname into buf */
|
|
||||||
MEMCPY(hostname, name, namelen);
|
|
||||||
hostname[namelen] = 0;
|
|
||||||
|
|
||||||
/* fill hostent */
|
|
||||||
h->addr_list[0] = &h->addr;
|
|
||||||
h->addr_list[1] = NULL;
|
|
||||||
h->aliases = NULL;
|
|
||||||
ret->h_name = hostname;
|
|
||||||
ret->h_aliases = &h->aliases;
|
|
||||||
ret->h_addrtype = AF_INET;
|
|
||||||
ret->h_length = sizeof(ip_addr_t);
|
|
||||||
ret->h_addr_list = (char**)&h->addr_list;
|
|
||||||
|
|
||||||
/* set result != NULL */
|
|
||||||
*result = ret;
|
|
||||||
|
|
||||||
/* return success */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
|
|
||||||
* any additional storage associated with those structures. If the ai_next field
|
|
||||||
* of the structure is not null, the entire list of structures is freed.
|
|
||||||
*
|
|
||||||
* @param ai struct addrinfo to free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
lwip_freeaddrinfo(struct addrinfo *ai)
|
|
||||||
{
|
|
||||||
struct addrinfo *next;
|
|
||||||
|
|
||||||
while (ai != NULL) {
|
|
||||||
next = ai->ai_next;
|
|
||||||
memp_free(MEMP_NETDB, ai);
|
|
||||||
ai = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the name of a service location (for example, a host name) and/or
|
|
||||||
* a service name and returns a set of socket addresses and associated
|
|
||||||
* information to be used in creating a socket with which to address the
|
|
||||||
* specified service.
|
|
||||||
* Memory for the result is allocated internally and must be freed by calling
|
|
||||||
* lwip_freeaddrinfo()!
|
|
||||||
*
|
|
||||||
* Due to a limitation in dns_gethostbyname, only the first address of a
|
|
||||||
* host is returned.
|
|
||||||
* Also, service names are not supported (only port numbers)!
|
|
||||||
*
|
|
||||||
* @param nodename descriptive name or address string of the host
|
|
||||||
* (may be NULL -> local address)
|
|
||||||
* @param servname port number as string of NULL
|
|
||||||
* @param hints structure containing input values that set socktype and protocol
|
|
||||||
* @param res pointer to a pointer where to store the result (set to NULL on failure)
|
|
||||||
* @return 0 on success, non-zero on failure
|
|
||||||
*
|
|
||||||
* @todo: implement AI_ADDRCONFIG
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lwip_getaddrinfo(const char *nodename, const char *servname,
|
|
||||||
const struct addrinfo *hints, struct addrinfo **res)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
ip_addr_t addr;
|
|
||||||
struct addrinfo *ai;
|
|
||||||
struct sockaddr_storage *sa = NULL;
|
|
||||||
int port_nr = 0;
|
|
||||||
size_t total_size;
|
|
||||||
size_t namelen = 0;
|
|
||||||
int ai_family;
|
|
||||||
|
|
||||||
if (res == NULL) {
|
|
||||||
return EAI_FAIL;
|
|
||||||
}
|
|
||||||
*res = NULL;
|
|
||||||
if ((nodename == NULL) && (servname == NULL)) {
|
|
||||||
return EAI_NONAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hints != NULL) {
|
|
||||||
ai_family = hints->ai_family;
|
|
||||||
if ((ai_family != AF_UNSPEC)
|
|
||||||
#if LWIP_IPV4
|
|
||||||
&& (ai_family != AF_INET)
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#if LWIP_IPV6
|
|
||||||
&& (ai_family != AF_INET6)
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
) {
|
|
||||||
return EAI_FAMILY;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ai_family = AF_UNSPEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (servname != NULL) {
|
|
||||||
/* service name specified: convert to port number
|
|
||||||
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
|
|
||||||
port_nr = atoi(servname);
|
|
||||||
if ((port_nr <= 0) || (port_nr > 0xffff)) {
|
|
||||||
return EAI_SERVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodename != NULL) {
|
|
||||||
/* service location specified, try to resolve */
|
|
||||||
if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
|
|
||||||
/* no DNS lookup, just parse for an address string */
|
|
||||||
if (!ipaddr_aton(nodename, &addr)) {
|
|
||||||
return EAI_NONAME;
|
|
||||||
}
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
|
|
||||||
(!IP_IS_V6_VAL(addr) && ai_family == AF_INET6)) {
|
|
||||||
return EAI_NONAME;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
} else {
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
/* AF_UNSPEC: prefer IPv4 */
|
|
||||||
u8_t type = NETCONN_DNS_IPV4_IPV6;
|
|
||||||
if (ai_family == AF_INET) {
|
|
||||||
type = NETCONN_DNS_IPV4;
|
|
||||||
} else if (ai_family == AF_INET6) {
|
|
||||||
type = NETCONN_DNS_IPV6;
|
|
||||||
if (hints->ai_flags & AI_V4MAPPED) {
|
|
||||||
type = NETCONN_DNS_IPV6_IPV4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
return EAI_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* service location specified, use loopback address */
|
|
||||||
if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
|
|
||||||
ip_addr_set_any(ai_family == AF_INET6, &addr);
|
|
||||||
} else {
|
|
||||||
ip_addr_set_loopback(ai_family == AF_INET6, &addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
if (ai_family == AF_INET6 && (hints->ai_flags & AI_V4MAPPED)
|
|
||||||
&& IP_GET_TYPE(&addr) == IPADDR_TYPE_V4) {
|
|
||||||
/* Convert native V4 address to a V4-mapped IPV6 address */
|
|
||||||
ip_addr_make_ip4_mapped_ip6(&addr, &addr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
|
|
||||||
if (nodename != NULL) {
|
|
||||||
namelen = strlen(nodename);
|
|
||||||
if (namelen > DNS_MAX_NAME_LENGTH) {
|
|
||||||
/* invalid name length */
|
|
||||||
return EAI_FAIL;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
|
|
||||||
total_size += namelen + 1;
|
|
||||||
}
|
|
||||||
/* If this fails, please report to lwip-devel! :-) */
|
|
||||||
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
|
|
||||||
total_size <= NETDB_ELEM_SIZE);
|
|
||||||
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
|
|
||||||
if (ai == NULL) {
|
|
||||||
return EAI_MEMORY;
|
|
||||||
}
|
|
||||||
memset(ai, 0, total_size);
|
|
||||||
sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo));
|
|
||||||
if (IP_IS_V6_VAL(addr)) {
|
|
||||||
#if LWIP_IPV6
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
|
|
||||||
/* set up sockaddr */
|
|
||||||
inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_len = sizeof(struct sockaddr_in6);
|
|
||||||
sa6->sin6_port = htons((u16_t)port_nr);
|
|
||||||
ai->ai_family = AF_INET6;
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
} else {
|
|
||||||
#if LWIP_IPV4
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
|
|
||||||
/* set up sockaddr */
|
|
||||||
inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_len = sizeof(struct sockaddr_in);
|
|
||||||
sa4->sin_port = htons((u16_t)port_nr);
|
|
||||||
ai->ai_family = AF_INET;
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up addrinfo */
|
|
||||||
if (hints != NULL) {
|
|
||||||
/* copy socktype & protocol from hints if specified */
|
|
||||||
ai->ai_socktype = hints->ai_socktype;
|
|
||||||
ai->ai_protocol = hints->ai_protocol;
|
|
||||||
}
|
|
||||||
if (nodename != NULL) {
|
|
||||||
/* copy nodename to canonname if specified */
|
|
||||||
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
|
|
||||||
MEMCPY(ai->ai_canonname, nodename, namelen);
|
|
||||||
ai->ai_canonname[namelen] = 0;
|
|
||||||
}
|
|
||||||
ai->ai_addrlen = sizeof(struct sockaddr_storage);
|
|
||||||
ai->ai_addr = (struct sockaddr*)sa;
|
|
||||||
|
|
||||||
*res = ai;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
|
|
@ -1,206 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Network Interface Sequential API module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/netifapi.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
|
|
||||||
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
|
|
||||||
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name)
|
|
||||||
#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name)
|
|
||||||
#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call netif_add() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
netifapi_do_netif_add(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)m;
|
|
||||||
|
|
||||||
if (!netif_add( msg->netif,
|
|
||||||
#if LWIP_IPV4
|
|
||||||
API_EXPR_REF(msg->msg.add.ipaddr),
|
|
||||||
API_EXPR_REF(msg->msg.add.netmask),
|
|
||||||
API_EXPR_REF(msg->msg.add.gw),
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
msg->msg.add.state,
|
|
||||||
msg->msg.add.init,
|
|
||||||
msg->msg.add.input)) {
|
|
||||||
return ERR_IF;
|
|
||||||
} else {
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/**
|
|
||||||
* Call netif_set_addr() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
netifapi_do_netif_set_addr(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)m;
|
|
||||||
|
|
||||||
netif_set_addr( msg->netif,
|
|
||||||
API_EXPR_REF(msg->msg.add.ipaddr),
|
|
||||||
API_EXPR_REF(msg->msg.add.netmask),
|
|
||||||
API_EXPR_REF(msg->msg.add.gw));
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
netifapi_do_netif_common(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)m;
|
|
||||||
|
|
||||||
if (msg->msg.common.errtfunc != NULL) {
|
|
||||||
return msg->msg.common.errtfunc(msg->netif);
|
|
||||||
} else {
|
|
||||||
msg->msg.common.voidfunc(msg->netif);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call netif_add() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*
|
|
||||||
* @note for params @see netif_add()
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netifapi_netif_add(struct netif *netif,
|
|
||||||
#if LWIP_IPV4
|
|
||||||
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
void *state, netif_init_fn init, netif_input_fn input)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
if (ipaddr == NULL) {
|
|
||||||
ipaddr = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
if (netmask == NULL) {
|
|
||||||
netmask = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
if (gw == NULL) {
|
|
||||||
gw = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
|
||||||
#if LWIP_IPV4
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.state = state;
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.init = init;
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.input = input;
|
|
||||||
err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
|
|
||||||
NETIFAPI_VAR_FREE(msg);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/**
|
|
||||||
* Call netif_set_addr() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*
|
|
||||||
* @note for params @see netif_set_addr()
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netifapi_netif_set_addr(struct netif *netif,
|
|
||||||
const ip4_addr_t *ipaddr,
|
|
||||||
const ip4_addr_t *netmask,
|
|
||||||
const ip4_addr_t *gw)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
|
||||||
|
|
||||||
if (ipaddr == NULL) {
|
|
||||||
ipaddr = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
if (netmask == NULL) {
|
|
||||||
netmask = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
if (gw == NULL) {
|
|
||||||
gw = IP4_ADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
|
||||||
err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
|
|
||||||
NETIFAPI_VAR_FREE(msg);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
|
|
||||||
* way by running that function inside the tcpip_thread context.
|
|
||||||
*
|
|
||||||
* @note use only for functions where there is only "netif" parameter.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
|
||||||
netifapi_errt_fn errtfunc)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
|
||||||
|
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
|
|
||||||
NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
|
|
||||||
err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
|
|
||||||
NETIFAPI_VAR_FREE(msg);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_NETIF_API */
|
|
|
@ -1,371 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Point To Point Protocol Sequential API module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pppapi.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
#include "netif/ppp/pppoe.h"
|
|
||||||
#include "netif/ppp/pppol2tp.h"
|
|
||||||
#include "netif/ppp/pppos.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_set_default() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_set_default(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
ppp_set_default(msg->msg.ppp);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_set_default() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pppapi_set_default(ppp_pcb *pcb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
tcpip_api_call(pppapi_do_ppp_set_default, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_set_auth() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_set_auth(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
ppp_set_auth(msg->msg.ppp, msg->msg.msg.setauth.authtype,
|
|
||||||
msg->msg.msg.setauth.user, msg->msg.msg.setauth.passwd);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_set_auth() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.setauth.authtype = authtype;
|
|
||||||
msg.msg.msg.setauth.user = user;
|
|
||||||
msg.msg.msg.setauth.passwd = passwd;
|
|
||||||
tcpip_api_call(pppapi_do_ppp_set_auth, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if PPP_NOTIFY_PHASE
|
|
||||||
/**
|
|
||||||
* Call ppp_set_notify_phase_callback() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.function = pppapi_do_ppp_set_notify_phase_callback;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb;
|
|
||||||
tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &msg.call);
|
|
||||||
}
|
|
||||||
#endif /* PPP_NOTIFY_PHASE */
|
|
||||||
|
|
||||||
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
/**
|
|
||||||
* Call pppos_create() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_pppos_create(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)(m);
|
|
||||||
|
|
||||||
msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb,
|
|
||||||
msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call pppos_create() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
ppp_pcb*
|
|
||||||
pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb,
|
|
||||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.msg.serialcreate.pppif = pppif;
|
|
||||||
msg.msg.msg.serialcreate.output_cb = output_cb;
|
|
||||||
msg.msg.msg.serialcreate.link_status_cb = link_status_cb;
|
|
||||||
msg.msg.msg.serialcreate.ctx_cb = ctx_cb;
|
|
||||||
tcpip_api_call(pppapi_do_pppos_create, &msg.call);
|
|
||||||
return msg.msg.ppp;
|
|
||||||
}
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
#if PPPOE_SUPPORT
|
|
||||||
/**
|
|
||||||
* Call pppoe_create() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_pppoe_create(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif,
|
|
||||||
msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name,
|
|
||||||
msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call pppoe_create() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
ppp_pcb*
|
|
||||||
pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name,
|
|
||||||
const char *concentrator_name, ppp_link_status_cb_fn link_status_cb,
|
|
||||||
void *ctx_cb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.msg.ethernetcreate.pppif = pppif;
|
|
||||||
msg.msg.msg.ethernetcreate.ethif = ethif;
|
|
||||||
msg.msg.msg.ethernetcreate.service_name = service_name;
|
|
||||||
msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name;
|
|
||||||
msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb;
|
|
||||||
msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb;
|
|
||||||
tcpip_api_call(pppapi_do_pppoe_create, &msg.call);
|
|
||||||
return msg.msg.ppp;
|
|
||||||
}
|
|
||||||
#endif /* PPPOE_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
#if PPPOL2TP_SUPPORT
|
|
||||||
/**
|
|
||||||
* Call pppol2tp_create() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_pppol2tp_create(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif,
|
|
||||||
msg->msg.msg.l2tpcreate.netif, msg->msg.msg.l2tpcreate.ipaddr, msg->msg.msg.l2tpcreate.port,
|
|
||||||
#if PPPOL2TP_AUTH_SUPPORT
|
|
||||||
msg->msg.msg.l2tpcreate.secret,
|
|
||||||
msg->msg.msg.l2tpcreate.secret_len,
|
|
||||||
#else /* PPPOL2TP_AUTH_SUPPORT */
|
|
||||||
NULL,
|
|
||||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
|
||||||
msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call pppol2tp_create() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
ppp_pcb*
|
|
||||||
pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port,
|
|
||||||
const u8_t *secret, u8_t secret_len,
|
|
||||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.msg.l2tpcreate.pppif = pppif;
|
|
||||||
msg.msg.msg.l2tpcreate.netif = netif;
|
|
||||||
msg.msg.msg.l2tpcreate.ipaddr = ipaddr;
|
|
||||||
msg.msg.msg.l2tpcreate.port = port;
|
|
||||||
#if PPPOL2TP_AUTH_SUPPORT
|
|
||||||
msg.msg.msg.l2tpcreate.secret = secret;
|
|
||||||
msg.msg.msg.l2tpcreate.secret_len = secret_len;
|
|
||||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
|
||||||
msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb;
|
|
||||||
msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb;
|
|
||||||
tcpip_api_call(pppapi_do_pppol2tp_create, &msg.call);
|
|
||||||
return msg.msg.ppp;
|
|
||||||
}
|
|
||||||
#endif /* PPPOL2TP_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_connect() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_connect(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_connect() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pppapi_connect(ppp_pcb *pcb, u16_t holdoff)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.connect.holdoff = holdoff;
|
|
||||||
return tcpip_api_call(pppapi_do_ppp_connect, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if PPP_SERVER
|
|
||||||
/**
|
|
||||||
* Call ppp_listen() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
pppapi_do_ppp_listen(struct pppapi_msg_msg *msg)
|
|
||||||
{
|
|
||||||
msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs);
|
|
||||||
TCPIP_PPPAPI_ACK(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_listen() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.function = pppapi_do_ppp_listen;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.listen.addrs = addrs;
|
|
||||||
TCPIP_PPPAPI(&msg);
|
|
||||||
return msg.msg.err;
|
|
||||||
}
|
|
||||||
#endif /* PPP_SERVER */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_close() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_close(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_close() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pppapi_close(ppp_pcb *pcb, u8_t nocarrier)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.close.nocarrier = nocarrier;
|
|
||||||
return tcpip_api_call(pppapi_do_ppp_close, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_free() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_free(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
return ppp_free(msg->msg.ppp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_free() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pppapi_free(ppp_pcb *pcb)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
return tcpip_api_call(pppapi_do_ppp_free, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_ioctl() inside the tcpip_thread context.
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
pppapi_do_ppp_ioctl(struct tcpip_api_call *m)
|
|
||||||
{
|
|
||||||
struct pppapi_msg *msg = (struct pppapi_msg *)m;
|
|
||||||
|
|
||||||
return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call ppp_ioctl() in a thread-safe way by running that function inside the
|
|
||||||
* tcpip_thread context.
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg)
|
|
||||||
{
|
|
||||||
struct pppapi_msg msg;
|
|
||||||
msg.msg.ppp = pcb;
|
|
||||||
msg.msg.msg.ioctl.cmd = cmd;
|
|
||||||
msg.msg.msg.ioctl.arg = arg;
|
|
||||||
return tcpip_api_call(pppapi_do_ppp_ioctl, &msg.call);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_PPP_API */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,567 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Sequential API Main thread module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
#include "lwip/priv/api_msg.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/init.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "netif/etharp.h"
|
|
||||||
|
|
||||||
#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
|
|
||||||
#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
|
|
||||||
#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name)
|
|
||||||
#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
|
|
||||||
|
|
||||||
/* global variables */
|
|
||||||
static tcpip_init_done_fn tcpip_init_done;
|
|
||||||
static void *tcpip_init_done_arg;
|
|
||||||
static sys_mbox_t mbox;
|
|
||||||
sys_thread_t g_lwip_task = NULL;
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
/** The global semaphore to lock the stack. */
|
|
||||||
sys_mutex_t lock_tcpip_core;
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
#if LWIP_TIMERS
|
|
||||||
/* wait for a message, timeouts are processed while waiting */
|
|
||||||
#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
|
|
||||||
#else /* LWIP_TIMERS */
|
|
||||||
/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
|
|
||||||
#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
|
|
||||||
#endif /* LWIP_TIMERS */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main lwIP thread. This thread has exclusive access to lwIP core functions
|
|
||||||
* (unless access to them is not locked). Other threads communicate with this
|
|
||||||
* thread using message boxes.
|
|
||||||
*
|
|
||||||
* It also starts all the timers to make sure they are running in the right
|
|
||||||
* thread context.
|
|
||||||
*
|
|
||||||
* @param arg unused argument
|
|
||||||
*/
|
|
||||||
static void ESP_IRAM_ATTR
|
|
||||||
tcpip_thread(void *arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
struct tcpip_msg *msg;
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
if (tcpip_init_done != NULL) {
|
|
||||||
tcpip_init_done(tcpip_init_done_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LOCK_TCPIP_CORE();
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
|
|
||||||
/* MAIN Loop */
|
|
||||||
UNLOCK_TCPIP_CORE();
|
|
||||||
LWIP_TCPIP_THREAD_ALIVE();
|
|
||||||
/* wait for a message, timeouts are processed while waiting */
|
|
||||||
TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
|
|
||||||
LOCK_TCPIP_CORE();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (msg == NULL) {
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
|
|
||||||
LWIP_ASSERT("tcpip_thread: invalid message", 0);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch (msg->type) {
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
case TCPIP_MSG_API:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
|
|
||||||
msg->msg.api.function(msg->msg.api.msg);
|
|
||||||
break;
|
|
||||||
case TCPIP_MSG_API_CALL:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
|
|
||||||
msg->msg.api_call->err = msg->msg.api_call->function(msg->msg.api_call);
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_sem_signal(msg->msg.api_call->sem);
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
sys_sem_signal(&msg->msg.api_call->sem);
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
break;
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
|
|
||||||
case TCPIP_MSG_INPKT:
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
if(msg->msg.inp.p != NULL && msg->msg.inp.netif != NULL) {
|
|
||||||
#endif
|
|
||||||
msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
|
|
||||||
#if ESP_LWIP
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
|
||||||
|
|
||||||
break;
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_TIMEOUT
|
|
||||||
case TCPIP_MSG_TIMEOUT:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
|
|
||||||
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
|
|
||||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
|
||||||
break;
|
|
||||||
case TCPIP_MSG_UNTIMEOUT:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
|
|
||||||
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
|
|
||||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
|
||||||
break;
|
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
|
||||||
|
|
||||||
case TCPIP_MSG_CALLBACK:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
|
||||||
msg->msg.cb.function(msg->msg.cb.ctx);
|
|
||||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TCPIP_MSG_CALLBACK_STATIC:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
|
|
||||||
msg->msg.cb.function(msg->msg.cb.ctx);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
|
|
||||||
LWIP_ASSERT("tcpip_thread: invalid message", 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass a received packet to tcpip_thread for input processing
|
|
||||||
*
|
|
||||||
* @param p the received packet
|
|
||||||
* @param inp the network interface on which the packet was received
|
|
||||||
* @param input_fn input function to call
|
|
||||||
*/
|
|
||||||
err_t ESP_IRAM_ATTR
|
|
||||||
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
|
|
||||||
{
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT
|
|
||||||
err_t ret;
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
|
|
||||||
LOCK_TCPIP_CORE();
|
|
||||||
ret = input_fn(p, inp);
|
|
||||||
UNLOCK_TCPIP_CORE();
|
|
||||||
return ret;
|
|
||||||
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
|
||||||
struct tcpip_msg *msg;
|
|
||||||
|
|
||||||
if (!sys_mbox_valid_val(mbox)) {
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
|
|
||||||
if (msg == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->type = TCPIP_MSG_INPKT;
|
|
||||||
msg->msg.inp.p = p;
|
|
||||||
msg->msg.inp.netif = inp;
|
|
||||||
msg->msg.inp.input_fn = input_fn;
|
|
||||||
#if ESP_PERF
|
|
||||||
if (p->len > DBG_PERF_FILTER_LEN) {
|
|
||||||
DBG_PERF_PATH_SET(DBG_PERF_DIR_RX, DBG_PERF_POINT_WIFI_OUT);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
|
|
||||||
ESP_STATS_DROP_INC(esp.tcpip_inpkt_post_fail);
|
|
||||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass a received packet to tcpip_thread for input processing with
|
|
||||||
* ethernet_input or ip_input
|
|
||||||
*
|
|
||||||
* @param p the received packet, p->payload pointing to the Ethernet header or
|
|
||||||
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
|
|
||||||
* NETIF_FLAG_ETHERNET flags)
|
|
||||||
* @param inp the network interface on which the packet was received
|
|
||||||
*/
|
|
||||||
err_t ESP_IRAM_ATTR
|
|
||||||
tcpip_input(struct pbuf *p, struct netif *inp)
|
|
||||||
{
|
|
||||||
#if LWIP_ETHERNET
|
|
||||||
if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
|
|
||||||
return tcpip_inpkt(p, inp, ethernet_input);
|
|
||||||
} else
|
|
||||||
#endif /* LWIP_ETHERNET */
|
|
||||||
return tcpip_inpkt(p, inp, ip_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call a specific function in the thread context of
|
|
||||||
* tcpip_thread for easy access synchronization.
|
|
||||||
* A function called in that way may access lwIP core code
|
|
||||||
* without fearing concurrent access.
|
|
||||||
*
|
|
||||||
* @param f the function to call
|
|
||||||
* @param ctx parameter passed to f
|
|
||||||
* @param block 1 to block until the request is posted, 0 to non-blocking mode
|
|
||||||
* @return ERR_OK if the function was called, another err_t if not
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
|
|
||||||
{
|
|
||||||
struct tcpip_msg *msg;
|
|
||||||
|
|
||||||
if (sys_mbox_valid_val(mbox)) {
|
|
||||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
|
||||||
if (msg == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->type = TCPIP_MSG_CALLBACK;
|
|
||||||
msg->msg.cb.function = function;
|
|
||||||
msg->msg.cb.ctx = ctx;
|
|
||||||
if (block) {
|
|
||||||
sys_mbox_post(&mbox, msg);
|
|
||||||
} else {
|
|
||||||
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
|
|
||||||
ESP_STATS_DROP_INC(esp.tcpip_cb_post_fail);
|
|
||||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_TIMEOUT
|
|
||||||
/**
|
|
||||||
* call sys_timeout in tcpip_thread
|
|
||||||
*
|
|
||||||
* @param msec time in milliseconds for timeout
|
|
||||||
* @param h function to be called on timeout
|
|
||||||
* @param arg argument to pass to timeout function h
|
|
||||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|
||||||
{
|
|
||||||
struct tcpip_msg *msg;
|
|
||||||
|
|
||||||
if (sys_mbox_valid_val(mbox)) {
|
|
||||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
|
||||||
if (msg == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->type = TCPIP_MSG_TIMEOUT;
|
|
||||||
msg->msg.tmo.msecs = msecs;
|
|
||||||
msg->msg.tmo.h = h;
|
|
||||||
msg->msg.tmo.arg = arg;
|
|
||||||
sys_mbox_post(&mbox, msg);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* call sys_untimeout in tcpip_thread
|
|
||||||
*
|
|
||||||
* @param msec time in milliseconds for timeout
|
|
||||||
* @param h function to be called on timeout
|
|
||||||
* @param arg argument to pass to timeout function h
|
|
||||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
tcpip_untimeout(sys_timeout_handler h, void *arg)
|
|
||||||
{
|
|
||||||
struct tcpip_msg *msg;
|
|
||||||
|
|
||||||
if (sys_mbox_valid_val(mbox)) {
|
|
||||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
|
||||||
if (msg == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->type = TCPIP_MSG_UNTIMEOUT;
|
|
||||||
msg->msg.tmo.h = h;
|
|
||||||
msg->msg.tmo.arg = arg;
|
|
||||||
sys_mbox_post(&mbox, msg);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
|
||||||
|
|
||||||
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
/**
|
|
||||||
* Generic way to dispatch an API message in TCPIP thread.
|
|
||||||
*
|
|
||||||
* @param fn function to be called from TCPIP thread
|
|
||||||
* @param apimsg argument to API function
|
|
||||||
* @param sem semaphore to wait on
|
|
||||||
* @return ERR_OK if the function was called, another err_t if not
|
|
||||||
*/
|
|
||||||
err_t ESP_IRAM_ATTR
|
|
||||||
tcpip_send_api_msg(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem)
|
|
||||||
{
|
|
||||||
LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
|
|
||||||
|
|
||||||
if (sys_mbox_valid_val(mbox)) {
|
|
||||||
TCPIP_MSG_VAR_DECLARE(msg);
|
|
||||||
|
|
||||||
TCPIP_MSG_VAR_ALLOC(msg);
|
|
||||||
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
|
|
||||||
TCPIP_MSG_VAR_REF(msg).msg.api.function = fn;
|
|
||||||
TCPIP_MSG_VAR_REF(msg).msg.api.msg = apimsg;
|
|
||||||
sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
|
|
||||||
sys_arch_sem_wait(sem, 0);
|
|
||||||
TCPIP_MSG_VAR_FREE(msg);
|
|
||||||
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call *call)
|
|
||||||
{
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
err_t err;
|
|
||||||
LOCK_TCPIP_CORE();
|
|
||||||
err = fn(call);
|
|
||||||
UNLOCK_TCPIP_CORE();
|
|
||||||
return err;
|
|
||||||
#else
|
|
||||||
if (sys_mbox_valid_val(mbox)) {
|
|
||||||
TCPIP_MSG_VAR_DECLARE(msg);
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
call->sem = LWIP_NETCONN_THREAD_SEM_GET();
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
err = sys_sem_new(&call->sem, 0);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
TCPIP_MSG_VAR_ALLOC(msg);
|
|
||||||
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
|
|
||||||
TCPIP_MSG_VAR_REF(msg).msg.api_call = call;
|
|
||||||
TCPIP_MSG_VAR_REF(msg).msg.api_call->function = fn;
|
|
||||||
sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_arch_sem_wait(call->sem, 0);
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
sys_arch_sem_wait(&call->sem, 0);
|
|
||||||
sys_sem_free(&call->sem);
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
TCPIP_MSG_VAR_FREE(msg);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a structure for a static callback message and initialize it.
|
|
||||||
* This is intended to be used to send "static" messages from interrupt context.
|
|
||||||
*
|
|
||||||
* @param function the function to call
|
|
||||||
* @param ctx parameter passed to function
|
|
||||||
* @return a struct pointer to pass to tcpip_trycallback().
|
|
||||||
*/
|
|
||||||
struct tcpip_callback_msg*
|
|
||||||
tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
|
|
||||||
{
|
|
||||||
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
|
||||||
if (msg == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
msg->type = TCPIP_MSG_CALLBACK_STATIC;
|
|
||||||
msg->msg.cb.function = function;
|
|
||||||
msg->msg.cb.ctx = ctx;
|
|
||||||
return (struct tcpip_callback_msg*)msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free a callback message allocated by tcpip_callbackmsg_new().
|
|
||||||
*
|
|
||||||
* @param msg the message to free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
|
|
||||||
{
|
|
||||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to post a callback-message to the tcpip_thread mbox
|
|
||||||
* This is intended to be used to send "static" messages from interrupt context.
|
|
||||||
*
|
|
||||||
* @param msg pointer to the message to post
|
|
||||||
* @return sys_mbox_trypost() return code
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
tcpip_trycallback(struct tcpip_callback_msg* msg)
|
|
||||||
{
|
|
||||||
if (!sys_mbox_valid_val(mbox)) {
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
return sys_mbox_trypost(&mbox, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this module:
|
|
||||||
* - initialize all sub modules
|
|
||||||
* - start the tcpip_thread
|
|
||||||
*
|
|
||||||
* @param initfunc a function to call when tcpip_thread is running and finished initializing
|
|
||||||
* @param arg argument to pass to initfunc
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
lwip_init();
|
|
||||||
|
|
||||||
tcpip_init_done = initfunc;
|
|
||||||
tcpip_init_done_arg = arg;
|
|
||||||
if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
|
|
||||||
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
|
|
||||||
}
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
|
|
||||||
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
|
|
||||||
g_lwip_task = sys_thread_new(TCPIP_THREAD_NAME
|
|
||||||
, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n",
|
|
||||||
(u32_t)g_lwip_task,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple callback function used with tcpip_callback to free a pbuf
|
|
||||||
* (pbuf_free has a wrong signature for tcpip_callback)
|
|
||||||
*
|
|
||||||
* @param p The pbuf (chain) to be dereferenced.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
pbuf_free_int(void *p)
|
|
||||||
{
|
|
||||||
struct pbuf *q = (struct pbuf *)p;
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple wrapper function that allows you to free a pbuf from interrupt context.
|
|
||||||
*
|
|
||||||
* @param p The pbuf (chain) to be dereferenced.
|
|
||||||
* @return ERR_OK if callback could be enqueued, an err_t if not
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
pbuf_free_callback(struct pbuf *p)
|
|
||||||
{
|
|
||||||
return tcpip_callback_with_block(pbuf_free_int, p, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple wrapper function that allows you to free heap memory from
|
|
||||||
* interrupt context.
|
|
||||||
*
|
|
||||||
* @param m the heap memory to free
|
|
||||||
* @return ERR_OK if callback could be enqueued, an err_t if not
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
static void mem_free_local(void *arg)
|
|
||||||
{
|
|
||||||
mem_free(arg);
|
|
||||||
}
|
|
||||||
err_t mem_free_callback(void *m)
|
|
||||||
{
|
|
||||||
return tcpip_callback_with_block(mem_free_local, m, 0);
|
|
||||||
|
|
||||||
#else
|
|
||||||
err_t mem_free_callback(void *m)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return tcpip_callback_with_block(mem_free, m, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !NO_SYS */
|
|
|
@ -22,8 +22,8 @@
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "tcpip_adapter.h"
|
#include "tcpip_adapter.h"
|
||||||
|
|
||||||
#include "apps/dhcpserver.h"
|
#include "dhcpserver/dhcpserver.h"
|
||||||
#include "apps/dhcpserver_options.h"
|
#include "dhcpserver/dhcpserver_options.h"
|
||||||
|
|
||||||
#if ESP_DHCP
|
#if ESP_DHCP
|
||||||
|
|
||||||
|
@ -524,9 +524,7 @@ static void send_offer(struct dhcps_msg *m, u16_t len)
|
||||||
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
|
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
|
||||||
ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
|
ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
|
||||||
SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
|
SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
|
||||||
#if DHCPS_DEBUG
|
|
||||||
DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
|
DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p->ref != 0) {
|
if (p->ref != 0) {
|
||||||
#if DHCPS_DEBUG
|
#if DHCPS_DEBUG
|
||||||
|
@ -597,9 +595,7 @@ static void send_nak(struct dhcps_msg *m, u16_t len)
|
||||||
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
|
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
|
||||||
ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
|
ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
|
||||||
SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
|
SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
|
||||||
#if DHCPS_DEBUG
|
|
||||||
DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
|
DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p->ref != 0) {
|
if (p->ref != 0) {
|
||||||
#if DHCPS_DEBUG
|
#if DHCPS_DEBUG
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_ping.h"
|
#include "ping/esp_ping.h"
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
|
|
|
@ -42,14 +42,14 @@
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV4 && LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "ping.h"
|
#include "ping/ping.h"
|
||||||
|
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/raw.h"
|
#include "lwip/raw.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#include "lwip/timers.h"
|
#include "lwip/timeouts.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/inet_chksum.h"
|
||||||
|
|
||||||
#if PING_USE_SOCKETS
|
#if PING_USE_SOCKETS
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
#endif /* PING_USE_SOCKETS */
|
#endif /* PING_USE_SOCKETS */
|
||||||
|
|
||||||
#ifdef ESP_PING
|
#ifdef ESP_PING
|
||||||
#include "esp_ping.h"
|
#include "ping/esp_ping.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
|
@ -155,7 +155,7 @@ ping_send(int s, ip_addr_t *addr)
|
||||||
|
|
||||||
to.sin_len = sizeof(to);
|
to.sin_len = sizeof(to);
|
||||||
to.sin_family = AF_INET;
|
to.sin_family = AF_INET;
|
||||||
inet_addr_from_ipaddr(&to.sin_addr, ip_2_ip4(addr));
|
inet_addr_from_ip4addr(&to.sin_addr, ip_2_ip4(addr));
|
||||||
|
|
||||||
err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
|
err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ ping_recv(int s)
|
||||||
LWIP_DEBUGF( PING_DEBUG, ("ping: invalid sin_family\n"));
|
LWIP_DEBUGF( PING_DEBUG, ("ping: invalid sin_family\n"));
|
||||||
} else {
|
} else {
|
||||||
ip4_addr_t fromaddr;
|
ip4_addr_t fromaddr;
|
||||||
inet_addr_to_ipaddr(&fromaddr, &from.sin_addr);
|
inet_addr_to_ip4addr(&fromaddr, &from.sin_addr);
|
||||||
iphdr = (struct ip_hdr *)buf;
|
iphdr = (struct ip_hdr *)buf;
|
||||||
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
|
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
|
||||||
|
|
||||||
|
|
|
@ -1,716 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* SNTP client module
|
|
||||||
*
|
|
||||||
* This is simple "SNTP" client for the lwIP raw API.
|
|
||||||
* It is a minimal implementation of SNTPv4 as specified in RFC 4330.
|
|
||||||
*
|
|
||||||
* For a list of some public NTP servers, see this link :
|
|
||||||
* http://support.ntp.org/bin/view/Servers/NTPPoolServers
|
|
||||||
*
|
|
||||||
* @todo:
|
|
||||||
* - set/change servers at runtime
|
|
||||||
* - complete SNTP_CHECK_RESPONSE checks 3 and 4
|
|
||||||
* - support broadcast/multicast mode?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
|
|
||||||
* 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: Frédéric Bernon, Simon Goldschmidt
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "apps/sntp/sntp.h"
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/timers.h"
|
|
||||||
#include "lwip/udp.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/dhcp.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if LWIP_UDP
|
|
||||||
|
|
||||||
/* Handle support for more than one server via SNTP_MAX_SERVERS */
|
|
||||||
#if SNTP_MAX_SERVERS > 1
|
|
||||||
#define SNTP_SUPPORT_MULTIPLE_SERVERS 1
|
|
||||||
#else /* NTP_MAX_SERVERS > 1 */
|
|
||||||
#define SNTP_SUPPORT_MULTIPLE_SERVERS 0
|
|
||||||
#endif /* NTP_MAX_SERVERS > 1 */
|
|
||||||
|
|
||||||
#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK)
|
|
||||||
#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Configure behaviour depending on microsecond or second precision */
|
|
||||||
#ifdef SNTP_SET_SYSTEM_TIME_US
|
|
||||||
#define SNTP_CALC_TIME_US 1
|
|
||||||
#define SNTP_RECEIVE_TIME_SIZE 2
|
|
||||||
#else
|
|
||||||
#define SNTP_SET_SYSTEM_TIME_US(sec, us)
|
|
||||||
#define SNTP_CALC_TIME_US 0
|
|
||||||
#define SNTP_RECEIVE_TIME_SIZE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* the various debug levels for this file */
|
|
||||||
#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE)
|
|
||||||
#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE)
|
|
||||||
#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
|
|
||||||
#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
|
|
||||||
#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
|
|
||||||
|
|
||||||
#define SNTP_ERR_KOD 1
|
|
||||||
|
|
||||||
/* SNTP protocol defines */
|
|
||||||
#define SNTP_MSG_LEN 48
|
|
||||||
|
|
||||||
#define SNTP_OFFSET_LI_VN_MODE 0
|
|
||||||
#define SNTP_LI_MASK 0xC0
|
|
||||||
#define SNTP_LI_NO_WARNING 0x00
|
|
||||||
#define SNTP_LI_LAST_MINUTE_61_SEC 0x01
|
|
||||||
#define SNTP_LI_LAST_MINUTE_59_SEC 0x02
|
|
||||||
#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */
|
|
||||||
|
|
||||||
#define SNTP_VERSION_MASK 0x38
|
|
||||||
#define SNTP_VERSION (4/* NTP Version 4*/<<3)
|
|
||||||
|
|
||||||
#define SNTP_MODE_MASK 0x07
|
|
||||||
#define SNTP_MODE_CLIENT 0x03
|
|
||||||
#define SNTP_MODE_SERVER 0x04
|
|
||||||
#define SNTP_MODE_BROADCAST 0x05
|
|
||||||
|
|
||||||
#define SNTP_OFFSET_STRATUM 1
|
|
||||||
#define SNTP_STRATUM_KOD 0x00
|
|
||||||
|
|
||||||
#define SNTP_OFFSET_ORIGINATE_TIME 24
|
|
||||||
#define SNTP_OFFSET_RECEIVE_TIME 32
|
|
||||||
#define SNTP_OFFSET_TRANSMIT_TIME 40
|
|
||||||
|
|
||||||
/* number of seconds between 1900 and 1970 (MSB=1)*/
|
|
||||||
#define DIFF_SEC_1900_1970 (2208988800UL)
|
|
||||||
/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */
|
|
||||||
#define DIFF_SEC_1970_2036 (2085978496UL)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SNTP packet format (without optional fields)
|
|
||||||
* Timestamps are coded as 64 bits:
|
|
||||||
* - 32 bits seconds since Jan 01, 1970, 00:00
|
|
||||||
* - 32 bits seconds fraction (0-padded)
|
|
||||||
* For future use, if the MSB in the seconds part is set, seconds are based
|
|
||||||
* on Feb 07, 2036, 06:28:16.
|
|
||||||
*/
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct sntp_msg {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t li_vn_mode);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t stratum);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t poll);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t precision);
|
|
||||||
PACK_STRUCT_FIELD(u32_t root_delay);
|
|
||||||
PACK_STRUCT_FIELD(u32_t root_dispersion);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reference_identifier);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reference_timestamp[2]);
|
|
||||||
PACK_STRUCT_FIELD(u32_t originate_timestamp[2]);
|
|
||||||
PACK_STRUCT_FIELD(u32_t receive_timestamp[2]);
|
|
||||||
PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
static void sntp_request(void *arg);
|
|
||||||
|
|
||||||
/** The operating mode */
|
|
||||||
static u8_t sntp_opmode;
|
|
||||||
|
|
||||||
/** The UDP pcb used by the SNTP client */
|
|
||||||
static struct udp_pcb* sntp_pcb;
|
|
||||||
/** Names/Addresses of servers */
|
|
||||||
struct sntp_server {
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
char* name;
|
|
||||||
#endif /* SNTP_SERVER_DNS */
|
|
||||||
ip_addr_t addr;
|
|
||||||
};
|
|
||||||
static struct sntp_server sntp_servers[SNTP_MAX_SERVERS];
|
|
||||||
|
|
||||||
#if SNTP_GET_SERVERS_FROM_DHCP
|
|
||||||
static u8_t sntp_set_servers_from_dhcp;
|
|
||||||
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
|
|
||||||
#if SNTP_SUPPORT_MULTIPLE_SERVERS
|
|
||||||
/** The currently used server (initialized to 0) */
|
|
||||||
static u8_t sntp_current_server;
|
|
||||||
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
|
||||||
#define sntp_current_server 0
|
|
||||||
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
|
||||||
|
|
||||||
#if SNTP_RETRY_TIMEOUT_EXP
|
|
||||||
#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
|
|
||||||
/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */
|
|
||||||
static u32_t sntp_retry_timeout;
|
|
||||||
#else /* SNTP_RETRY_TIMEOUT_EXP */
|
|
||||||
#define SNTP_RESET_RETRY_TIMEOUT()
|
|
||||||
#define sntp_retry_timeout SNTP_RETRY_TIMEOUT
|
|
||||||
#endif /* SNTP_RETRY_TIMEOUT_EXP */
|
|
||||||
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 1
|
|
||||||
/** Saves the last server address to compare with response */
|
|
||||||
static ip_addr_t sntp_last_server_address;
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
|
||||||
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 2
|
|
||||||
/** Saves the last timestamp sent (which is sent back by the server)
|
|
||||||
* to compare against in response */
|
|
||||||
static u32_t sntp_last_timestamp_sent[2];
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SNTP processing of received timestamp
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_process(u32_t *receive_timestamp)
|
|
||||||
{
|
|
||||||
/* convert SNTP time (1900-based) to unix GMT time (1970-based)
|
|
||||||
* if MSB is 0, SNTP time is 2036-based!
|
|
||||||
*/
|
|
||||||
u32_t rx_secs = ntohl(receive_timestamp[0]);
|
|
||||||
int is_1900_based = ((rx_secs & 0x80000000) != 0);
|
|
||||||
u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036);
|
|
||||||
time_t tim = t;
|
|
||||||
|
|
||||||
#if SNTP_CALC_TIME_US
|
|
||||||
u32_t us = ntohl(receive_timestamp[1]) / 4295;
|
|
||||||
SNTP_SET_SYSTEM_TIME_US(t, us);
|
|
||||||
/* display local time from GMT time */
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us));
|
|
||||||
|
|
||||||
#else /* SNTP_CALC_TIME_US */
|
|
||||||
|
|
||||||
/* change system time and/or the update the RTC clock */
|
|
||||||
SNTP_SET_SYSTEM_TIME(t);
|
|
||||||
/* display local time from GMT time */
|
|
||||||
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim)));
|
|
||||||
#endif /* SNTP_CALC_TIME_US */
|
|
||||||
LWIP_UNUSED_ARG(tim);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize request struct to be sent to server.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_initialize_request(struct sntp_msg *req)
|
|
||||||
{
|
|
||||||
memset(req, 0, SNTP_MSG_LEN);
|
|
||||||
req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
|
|
||||||
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 2
|
|
||||||
{
|
|
||||||
u32_t sntp_time_sec, sntp_time_us;
|
|
||||||
/* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
|
|
||||||
SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
|
|
||||||
sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970);
|
|
||||||
req->transmit_timestamp[0] = sntp_last_timestamp_sent[0];
|
|
||||||
/* we send/save us instead of fraction to be faster... */
|
|
||||||
sntp_last_timestamp_sent[1] = htonl(sntp_time_us);
|
|
||||||
req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
|
|
||||||
}
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retry: send a new request (and increase retry timeout).
|
|
||||||
*
|
|
||||||
* @param arg is unused (only necessary to conform to sys_timeout)
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_retry(void* arg)
|
|
||||||
{
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
|
|
||||||
sntp_retry_timeout));
|
|
||||||
|
|
||||||
/* set up a timer to send a retry and increase the retry delay */
|
|
||||||
sys_timeout(sntp_retry_timeout, sntp_request, NULL);
|
|
||||||
|
|
||||||
#if SNTP_RETRY_TIMEOUT_EXP
|
|
||||||
{
|
|
||||||
u32_t new_retry_timeout;
|
|
||||||
/* increase the timeout for next retry */
|
|
||||||
new_retry_timeout = sntp_retry_timeout << 1;
|
|
||||||
/* limit to maximum timeout and prevent overflow */
|
|
||||||
if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
|
|
||||||
(new_retry_timeout > sntp_retry_timeout)) {
|
|
||||||
sntp_retry_timeout = new_retry_timeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SNTP_RETRY_TIMEOUT_EXP */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SNTP_SUPPORT_MULTIPLE_SERVERS
|
|
||||||
/**
|
|
||||||
* If Kiss-of-Death is received (or another packet parsing error),
|
|
||||||
* try the next server or retry the current server and increase the retry
|
|
||||||
* timeout if only one server is available.
|
|
||||||
* (implicitly, SNTP_MAX_SERVERS > 1)
|
|
||||||
*
|
|
||||||
* @param arg is unused (only necessary to conform to sys_timeout)
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_try_next_server(void* arg)
|
|
||||||
{
|
|
||||||
u8_t old_server, i;
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
old_server = sntp_current_server;
|
|
||||||
for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) {
|
|
||||||
sntp_current_server++;
|
|
||||||
if (sntp_current_server >= SNTP_MAX_SERVERS) {
|
|
||||||
sntp_current_server = 0;
|
|
||||||
}
|
|
||||||
if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr)
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
|| (sntp_servers[sntp_current_server].name != NULL)
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
|
|
||||||
(u16_t)sntp_current_server));
|
|
||||||
/* new server: reset retry timeout */
|
|
||||||
SNTP_RESET_RETRY_TIMEOUT();
|
|
||||||
/* instantly send a request to the next server */
|
|
||||||
sntp_request(NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* no other valid server found */
|
|
||||||
sntp_current_server = old_server;
|
|
||||||
sntp_retry(NULL);
|
|
||||||
}
|
|
||||||
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
|
||||||
/* Always retry on error if only one server is supported */
|
|
||||||
#define sntp_try_next_server sntp_retry
|
|
||||||
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
|
||||||
|
|
||||||
/** UDP recv callback for the sntp pcb */
|
|
||||||
static void
|
|
||||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
|
||||||
{
|
|
||||||
u8_t mode;
|
|
||||||
u8_t stratum;
|
|
||||||
u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
LWIP_UNUSED_ARG(pcb);
|
|
||||||
|
|
||||||
/* packet received: stop retry timeout */
|
|
||||||
sys_untimeout(sntp_try_next_server, NULL);
|
|
||||||
sys_untimeout(sntp_request, NULL);
|
|
||||||
|
|
||||||
err = ERR_ARG;
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 1
|
|
||||||
/* check server address and port */
|
|
||||||
if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) &&
|
|
||||||
(port == SNTP_PORT))
|
|
||||||
#else /* SNTP_CHECK_RESPONSE >= 1 */
|
|
||||||
LWIP_UNUSED_ARG(addr);
|
|
||||||
LWIP_UNUSED_ARG(port);
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
|
||||||
{
|
|
||||||
/* process the response */
|
|
||||||
if (p->tot_len == SNTP_MSG_LEN) {
|
|
||||||
pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
|
|
||||||
mode &= SNTP_MODE_MASK;
|
|
||||||
/* if this is a SNTP response... */
|
|
||||||
if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) ||
|
|
||||||
((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) {
|
|
||||||
pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
|
|
||||||
if (stratum == SNTP_STRATUM_KOD) {
|
|
||||||
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
|
|
||||||
err = SNTP_ERR_KOD;
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
|
|
||||||
} else {
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 2
|
|
||||||
/* check originate_timetamp against sntp_last_timestamp_sent */
|
|
||||||
u32_t originate_timestamp[2];
|
|
||||||
pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
|
|
||||||
if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
|
|
||||||
(originate_timestamp[1] != sntp_last_timestamp_sent[1]))
|
|
||||||
{
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
|
|
||||||
} else
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
|
||||||
/* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
|
|
||||||
{
|
|
||||||
/* correct answer */
|
|
||||||
err = ERR_OK;
|
|
||||||
pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
|
|
||||||
/* wait for correct response */
|
|
||||||
err = ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 1
|
|
||||||
else {
|
|
||||||
/* packet from wrong remote address or port, wait for correct response */
|
|
||||||
err = ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
|
||||||
pbuf_free(p);
|
|
||||||
if (err == ERR_OK) {
|
|
||||||
sntp_process(receive_timestamp);
|
|
||||||
|
|
||||||
/* Set up timeout for next request (only if poll response was received)*/
|
|
||||||
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
|
||||||
/* Correct response, reset retry timeout */
|
|
||||||
SNTP_RESET_RETRY_TIMEOUT();
|
|
||||||
|
|
||||||
sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
|
|
||||||
(u32_t)SNTP_UPDATE_DELAY));
|
|
||||||
}
|
|
||||||
} else if (err != ERR_TIMEOUT) {
|
|
||||||
/* Errors are only processed in case of an explicit poll response */
|
|
||||||
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
|
||||||
if (err == SNTP_ERR_KOD) {
|
|
||||||
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
|
|
||||||
sntp_try_next_server(NULL);
|
|
||||||
} else {
|
|
||||||
/* another error, try the same server again */
|
|
||||||
sntp_retry(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually send an sntp request to a server.
|
|
||||||
*
|
|
||||||
* @param server_addr resolved IP address of the SNTP server
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_send_request(const ip_addr_t *server_addr)
|
|
||||||
{
|
|
||||||
struct pbuf* p;
|
|
||||||
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
|
|
||||||
if (p != NULL) {
|
|
||||||
struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
|
|
||||||
/* initialize request message */
|
|
||||||
sntp_initialize_request(sntpmsg);
|
|
||||||
/* send request */
|
|
||||||
udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
|
|
||||||
/* free the pbuf after sending it */
|
|
||||||
pbuf_free(p);
|
|
||||||
/* set up receive timeout: try next server or retry on timeout */
|
|
||||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
|
|
||||||
#if SNTP_CHECK_RESPONSE >= 1
|
|
||||||
/* save server address to verify it in sntp_recv */
|
|
||||||
ip_addr_set(&sntp_last_server_address, server_addr);
|
|
||||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
|
|
||||||
(u32_t)SNTP_RETRY_TIMEOUT));
|
|
||||||
/* out of memory: set up a timer to send a retry */
|
|
||||||
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
/**
|
|
||||||
* DNS found callback when using DNS names as server address.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
|
|
||||||
{
|
|
||||||
LWIP_UNUSED_ARG(hostname);
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
if (ipaddr != NULL) {
|
|
||||||
/* Address resolved, send request */
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
|
|
||||||
sntp_send_request(ipaddr);
|
|
||||||
} else {
|
|
||||||
/* DNS resolving failed -> try another server */
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
|
|
||||||
sntp_try_next_server(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SNTP_SERVER_DNS */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send out an sntp request.
|
|
||||||
*
|
|
||||||
* @param arg is unused (only necessary to conform to sys_timeout)
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sntp_request(void *arg)
|
|
||||||
{
|
|
||||||
ip_addr_t sntp_server_address;
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
/* initialize SNTP server address */
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
if (sntp_servers[sntp_current_server].name) {
|
|
||||||
/* always resolve the name and rely on dns-internal caching & timeout */
|
|
||||||
ip_addr_set_zero(&sntp_servers[sntp_current_server].addr);
|
|
||||||
err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address,
|
|
||||||
sntp_dns_found, NULL);
|
|
||||||
if (err == ERR_INPROGRESS) {
|
|
||||||
/* DNS request sent, wait for sntp_dns_found being called */
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
|
|
||||||
return;
|
|
||||||
} else if (err == ERR_OK) {
|
|
||||||
sntp_servers[sntp_current_server].addr = sntp_server_address;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif /* SNTP_SERVER_DNS */
|
|
||||||
{
|
|
||||||
sntp_server_address = sntp_servers[sntp_current_server].addr;
|
|
||||||
err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == ERR_OK) {
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n",
|
|
||||||
ipaddr_ntoa(&sntp_server_address)));
|
|
||||||
sntp_send_request(&sntp_server_address);
|
|
||||||
} else {
|
|
||||||
/* address conversion failed, try another server */
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
|
|
||||||
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this module.
|
|
||||||
* Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_init(void)
|
|
||||||
{
|
|
||||||
#ifdef SNTP_SERVER_ADDRESS
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
sntp_setservername(0, SNTP_SERVER_ADDRESS);
|
|
||||||
#else
|
|
||||||
#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0
|
|
||||||
#endif
|
|
||||||
#endif /* SNTP_SERVER_ADDRESS */
|
|
||||||
|
|
||||||
if (sntp_pcb == NULL) {
|
|
||||||
sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
|
||||||
LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
|
|
||||||
if (sntp_pcb != NULL) {
|
|
||||||
udp_recv(sntp_pcb, sntp_recv, NULL);
|
|
||||||
|
|
||||||
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
|
||||||
SNTP_RESET_RETRY_TIMEOUT();
|
|
||||||
#if SNTP_STARTUP_DELAY
|
|
||||||
sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL);
|
|
||||||
#else
|
|
||||||
sntp_request(NULL);
|
|
||||||
#endif
|
|
||||||
} else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) {
|
|
||||||
ip_set_option(sntp_pcb, SOF_BROADCAST);
|
|
||||||
udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop this module.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_stop(void)
|
|
||||||
{
|
|
||||||
if (sntp_pcb != NULL) {
|
|
||||||
sys_untimeout(sntp_request, NULL);
|
|
||||||
udp_remove(sntp_pcb);
|
|
||||||
sntp_pcb = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get enabled state.
|
|
||||||
*/
|
|
||||||
u8_t sntp_enabled(void)
|
|
||||||
{
|
|
||||||
return (sntp_pcb != NULL)? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the operating mode.
|
|
||||||
* @param operating_mode one of the available operating modes
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_setoperatingmode(u8_t operating_mode)
|
|
||||||
{
|
|
||||||
LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY);
|
|
||||||
LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL);
|
|
||||||
sntp_opmode = operating_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operating mode.
|
|
||||||
*/
|
|
||||||
u8_t
|
|
||||||
sntp_getoperatingmode(void)
|
|
||||||
{
|
|
||||||
return sntp_opmode;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SNTP_GET_SERVERS_FROM_DHCP
|
|
||||||
/**
|
|
||||||
* Config SNTP server handling by IP address, name, or DHCP; clear table
|
|
||||||
* @param set_servers_from_dhcp enable or disable getting server addresses from dhcp
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_servermode_dhcp(int set_servers_from_dhcp)
|
|
||||||
{
|
|
||||||
u8_t new_mode = set_servers_from_dhcp ? 1 : 0;
|
|
||||||
if (sntp_set_servers_from_dhcp != new_mode) {
|
|
||||||
sntp_set_servers_from_dhcp = new_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize one of the NTP servers by IP address
|
|
||||||
*
|
|
||||||
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
|
||||||
* @param dnsserver IP address of the NTP server to set
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_setserver(u8_t idx, const ip_addr_t *server)
|
|
||||||
{
|
|
||||||
if (idx < SNTP_MAX_SERVERS) {
|
|
||||||
if (server != NULL) {
|
|
||||||
sntp_servers[idx].addr = (*server);
|
|
||||||
} else {
|
|
||||||
ip_addr_set_zero(&sntp_servers[idx].addr);
|
|
||||||
}
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
sntp_servers[idx].name = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP
|
|
||||||
/**
|
|
||||||
* Initialize one of the NTP servers by IP address, required by DHCP
|
|
||||||
*
|
|
||||||
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
|
||||||
* @param dnsserver IP address of the NTP server to set
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server)
|
|
||||||
{
|
|
||||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n",
|
|
||||||
(sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
|
|
||||||
ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num));
|
|
||||||
if (sntp_set_servers_from_dhcp && num) {
|
|
||||||
u8_t i;
|
|
||||||
for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) {
|
|
||||||
ip_addr_t addr;
|
|
||||||
ip_addr_copy_from_ip4(addr, server[i]);
|
|
||||||
sntp_setserver(i, &addr);
|
|
||||||
}
|
|
||||||
for (i = num; i < SNTP_MAX_SERVERS; i++) {
|
|
||||||
sntp_setserver(i, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain one of the currently configured by IP address (or DHCP) NTP servers
|
|
||||||
*
|
|
||||||
* @param numdns the index of the NTP server
|
|
||||||
* @return IP address of the indexed NTP server or "ip_addr_any" if the NTP
|
|
||||||
* server has not been configured by address (or at all).
|
|
||||||
*/
|
|
||||||
ip_addr_t
|
|
||||||
sntp_getserver(u8_t idx)
|
|
||||||
{
|
|
||||||
if (idx < SNTP_MAX_SERVERS) {
|
|
||||||
return sntp_servers[idx].addr;
|
|
||||||
}
|
|
||||||
return *IP_ADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
/**
|
|
||||||
* Initialize one of the NTP servers by name
|
|
||||||
*
|
|
||||||
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
|
||||||
* @param dnsserver DNS name of the NTP server to set, to be resolved at contact time
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sntp_setservername(u8_t idx, char *server)
|
|
||||||
{
|
|
||||||
if (idx < SNTP_MAX_SERVERS) {
|
|
||||||
sntp_servers[idx].name = server;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain one of the currently configured by name NTP servers.
|
|
||||||
*
|
|
||||||
* @param numdns the index of the NTP server
|
|
||||||
* @return IP address of the indexed NTP server or NULL if the NTP
|
|
||||||
* server has not been configured by name (or at all)
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sntp_getservername(u8_t idx)
|
|
||||||
{
|
|
||||||
if (idx < SNTP_MAX_SERVERS) {
|
|
||||||
return sntp_servers[idx].name;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif /* SNTP_SERVER_DNS */
|
|
||||||
|
|
||||||
#endif /* LWIP_UDP */
|
|
||||||
|
|
|
@ -1,25 +1,28 @@
|
||||||
#
|
#
|
||||||
# Component Makefile
|
# Component Makefile
|
||||||
#
|
#
|
||||||
|
COMPONENT_SUBMODULES += lwip
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS := \
|
COMPONENT_ADD_INCLUDEDIRS := \
|
||||||
include/lwip \
|
include/apps \
|
||||||
include/lwip/port \
|
lwip/src/include \
|
||||||
include/lwip/posix \
|
port/esp32/include \
|
||||||
apps/ping
|
port/esp32/include/arch
|
||||||
|
|
||||||
ifdef CONFIG_PPP_SUPPORT
|
|
||||||
LWIP_PPP_DIRS := netif/ppp/polarssl netif/ppp
|
|
||||||
else
|
|
||||||
LWIP_PPP_DIRS :=
|
|
||||||
endif
|
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := \
|
COMPONENT_SRCDIRS := \
|
||||||
api \
|
apps/dhcpserver \
|
||||||
apps apps/sntp apps/ping \
|
apps/ping \
|
||||||
core core/ipv4 core/ipv6 \
|
lwip/src/api \
|
||||||
$(LWIP_PPP_DIRS) netif \
|
lwip/src/apps/sntp \
|
||||||
port/freertos port/netif port/debug port
|
lwip/src/core \
|
||||||
|
lwip/src/core/ipv4 \
|
||||||
|
lwip/src/core/ipv6 \
|
||||||
|
lwip/src/netif \
|
||||||
|
lwip/src/netif/ppp \
|
||||||
|
port/esp32 \
|
||||||
|
port/esp32/freertos \
|
||||||
|
port/esp32/netif \
|
||||||
|
port/esp32/debug
|
||||||
|
|
||||||
CFLAGS += -Wno-address # lots of LWIP source files evaluate macros that check address of stack variables
|
CFLAGS += -Wno-address # lots of LWIP source files evaluate macros that check address of stack variables
|
||||||
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Common functions used throughout the stack.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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: Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are reference implementations of the byte swapping functions.
|
|
||||||
* Again with the aim of being simple, correct and fully portable.
|
|
||||||
* Byte swapping is the second thing you would want to optimize. You will
|
|
||||||
* need to port it to your architecture and in your cc.h:
|
|
||||||
*
|
|
||||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
|
||||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
|
||||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
|
||||||
*
|
|
||||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an u16_t from host- to network byte order.
|
|
||||||
*
|
|
||||||
* @param n u16_t in host byte order
|
|
||||||
* @return n in network byte order
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
lwip_htons(u16_t n)
|
|
||||||
{
|
|
||||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an u16_t from network- to host byte order.
|
|
||||||
*
|
|
||||||
* @param n u16_t in network byte order
|
|
||||||
* @return n in host byte order
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
lwip_ntohs(u16_t n)
|
|
||||||
{
|
|
||||||
return lwip_htons(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an u32_t from host- to network byte order.
|
|
||||||
*
|
|
||||||
* @param n u32_t in host byte order
|
|
||||||
* @return n in network byte order
|
|
||||||
*/
|
|
||||||
u32_t
|
|
||||||
lwip_htonl(u32_t n)
|
|
||||||
{
|
|
||||||
return ((n & 0xff) << 24) |
|
|
||||||
((n & 0xff00) << 8) |
|
|
||||||
((n & 0xff0000UL) >> 8) |
|
|
||||||
((n & 0xff000000UL) >> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an u32_t from network- to host byte order.
|
|
||||||
*
|
|
||||||
* @param n u32_t in network byte order
|
|
||||||
* @return n in host byte order
|
|
||||||
*/
|
|
||||||
u32_t
|
|
||||||
lwip_ntohl(u32_t n)
|
|
||||||
{
|
|
||||||
return lwip_htonl(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,612 +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 "lwip/ip_addr.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
|
|
||||||
u16_t lwip_standard_chksum(const void *dataptr, int len);
|
|
||||||
#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)
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
lwip_standard_chksum(const void *dataptr, int len)
|
|
||||||
{
|
|
||||||
u32_t acc;
|
|
||||||
u16_t src;
|
|
||||||
const u8_t *octetptr;
|
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
/* dataptr may be at odd or even addresses */
|
|
||||||
octetptr = (const 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)
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
lwip_standard_chksum(const void *dataptr, int len)
|
|
||||||
{
|
|
||||||
const u8_t *pb = (const u8_t *)dataptr;
|
|
||||||
const u16_t *ps;
|
|
||||||
u16_t 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 = (const u16_t *)(const void *)pb;
|
|
||||||
while (len > 1) {
|
|
||||||
sum += *ps++;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Consume left-over byte, if any */
|
|
||||||
if (len > 0) {
|
|
||||||
((u8_t *)&t)[0] = *(const u8_t *)ps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add end bytes */
|
|
||||||
sum += t;
|
|
||||||
|
|
||||||
/* Fold 32-bit sum to 16 bits
|
|
||||||
calling this twice is probably 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
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
lwip_standard_chksum(const void *dataptr, int len)
|
|
||||||
{
|
|
||||||
const u8_t *pb = (const u8_t *)dataptr;
|
|
||||||
const u16_t *ps;
|
|
||||||
u16_t t = 0;
|
|
||||||
const 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 = (const u16_t *)(const void*)pb;
|
|
||||||
|
|
||||||
if (((mem_ptr_t)ps & 3) && len > 1) {
|
|
||||||
sum += *ps++;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl = (const u32_t *)(const void*)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 = (const 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] = *(const u8_t *)ps;
|
|
||||||
}
|
|
||||||
|
|
||||||
sum += t; /* add end bytes */
|
|
||||||
|
|
||||||
/* Fold 32-bit sum to 16 bits
|
|
||||||
calling this twice is probably 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
|
|
||||||
|
|
||||||
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
|
||||||
static u16_t ESP_IRAM_ATTR
|
|
||||||
inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
|
|
||||||
{
|
|
||||||
struct pbuf *q;
|
|
||||||
u8_t 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
acc += (u32_t)htons((u16_t)proto);
|
|
||||||
acc += (u32_t)htons(proto_len);
|
|
||||||
|
|
||||||
/* Fold 32-bit sum to 16 bits
|
|
||||||
calling this twice is probably 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/* inet_chksum_pseudo:
|
|
||||||
*
|
|
||||||
* Calculates the IPv4 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 ESP_IRAM_ATTR
|
|
||||||
inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip4_addr_t *src, const ip4_addr_t *dest)
|
|
||||||
{
|
|
||||||
u32_t acc;
|
|
||||||
u32_t addr;
|
|
||||||
|
|
||||||
addr = ip4_addr_get_u32(src);
|
|
||||||
acc = (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = ip4_addr_get_u32(dest);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
/* fold down to 16 bits */
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
|
|
||||||
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/**
|
|
||||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
|
||||||
* IPv6 addresses are expected to be in network byte order.
|
|
||||||
*
|
|
||||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
|
||||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
|
||||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
|
||||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
|
||||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
|
||||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip6_addr_t *src, const ip6_addr_t *dest)
|
|
||||||
{
|
|
||||||
u32_t acc = 0;
|
|
||||||
u32_t addr;
|
|
||||||
u8_t addr_part;
|
|
||||||
|
|
||||||
for (addr_part = 0; addr_part < 4; addr_part++) {
|
|
||||||
addr = src->addr[addr_part];
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = dest->addr[addr_part];
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
}
|
|
||||||
/* fold down to 16 bits */
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
|
|
||||||
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/* ip_chksum_pseudo:
|
|
||||||
*
|
|
||||||
* Calculates the IPv4 or IPv6 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 ESP_IRAM_ATTR
|
|
||||||
ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip_addr_t *src, const ip_addr_t *dest)
|
|
||||||
{
|
|
||||||
#if LWIP_IPV6
|
|
||||||
if (IP_IS_V6(dest)) {
|
|
||||||
return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest));
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
else
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
#if LWIP_IPV4
|
|
||||||
{
|
|
||||||
return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest));
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
|
||||||
static u16_t
|
|
||||||
inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, u32_t acc)
|
|
||||||
{
|
|
||||||
struct pbuf *q;
|
|
||||||
u8_t swapped = 0;
|
|
||||||
u16_t chklen;
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
acc += (u32_t)htons((u16_t)proto);
|
|
||||||
acc += (u32_t)htons(proto_len);
|
|
||||||
|
|
||||||
/* Fold 32-bit sum to 16 bits
|
|
||||||
calling this twice is probably 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/* inet_chksum_pseudo_partial:
|
|
||||||
*
|
|
||||||
* Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
|
||||||
* IP addresses are expected to be in network byte order.
|
|
||||||
*
|
|
||||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
|
||||||
* @param src source ip address (used for checksum of pseudo header)
|
|
||||||
* @param dst destination ip address (used for checksum of pseudo header)
|
|
||||||
* @param proto ip protocol (used for checksum of pseudo header)
|
|
||||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
|
||||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest)
|
|
||||||
{
|
|
||||||
u32_t acc;
|
|
||||||
u32_t addr;
|
|
||||||
|
|
||||||
addr = ip4_addr_get_u32(src);
|
|
||||||
acc = (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = ip4_addr_get_u32(dest);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
/* fold down to 16 bits */
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
|
|
||||||
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/**
|
|
||||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
|
||||||
* IPv6 addresses are expected to be in network byte order. Will only compute for a
|
|
||||||
* portion of the payload.
|
|
||||||
*
|
|
||||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
|
||||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
|
||||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
|
||||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
|
||||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
|
||||||
* @param chksum_len number of payload bytes used to compute chksum
|
|
||||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest)
|
|
||||||
{
|
|
||||||
u32_t acc = 0;
|
|
||||||
u32_t addr;
|
|
||||||
u8_t addr_part;
|
|
||||||
|
|
||||||
for (addr_part = 0; addr_part < 4; addr_part++) {
|
|
||||||
addr = src->addr[addr_part];
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = dest->addr[addr_part];
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
}
|
|
||||||
/* fold down to 16 bits */
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
acc = FOLD_U32T(acc);
|
|
||||||
|
|
||||||
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/* ip_chksum_pseudo_partial:
|
|
||||||
*
|
|
||||||
* Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest)
|
|
||||||
{
|
|
||||||
#if LWIP_IPV6
|
|
||||||
if (IP_IS_V6(dest)) {
|
|
||||||
return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest));
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
else
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
#if LWIP_IPV4
|
|
||||||
{
|
|
||||||
return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest));
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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(const void *dataptr, u16_t len)
|
|
||||||
{
|
|
||||||
return (u16_t)~(unsigned int)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) */
|
|
|
@ -1,376 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Modules initialization
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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/init.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/sockets.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/raw.h"
|
|
||||||
#include "lwip/udp.h"
|
|
||||||
#include "lwip/priv/tcp_priv.h"
|
|
||||||
#include "lwip/autoip.h"
|
|
||||||
#include "lwip/igmp.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
#include "lwip/timers.h"
|
|
||||||
#include "netif/etharp.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "netif/ppp/ppp_impl.h"
|
|
||||||
|
|
||||||
#if ! ESP_PERF
|
|
||||||
/* Compile-time sanity checks for configuration errors.
|
|
||||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
|
||||||
*/
|
|
||||||
#ifndef BYTE_ORDER
|
|
||||||
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
|
|
||||||
#endif
|
|
||||||
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
|
||||||
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (!LWIP_UDP && LWIP_UDPLITE)
|
|
||||||
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (!LWIP_UDP && LWIP_DHCP)
|
|
||||||
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
|
|
||||||
#error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (!LWIP_UDP && LWIP_DNS)
|
|
||||||
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
|
|
||||||
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
|
|
||||||
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
|
|
||||||
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
|
|
||||||
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
|
|
||||||
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
|
||||||
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
|
|
||||||
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_IGMP && !LWIP_IPV4)
|
|
||||||
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
|
|
||||||
#error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
|
||||||
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
|
||||||
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
|
|
||||||
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
|
||||||
#endif
|
|
||||||
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
|
||||||
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
|
||||||
#endif
|
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
|
||||||
|
|
||||||
#if LWIP_WND_SCALE
|
|
||||||
//#if (LWIP_TCP && (TCP_WND > 0xffffffff))
|
|
||||||
//#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
|
|
||||||
//#endif
|
|
||||||
#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
|
|
||||||
#error "The maximum valid window scale value is 14!"
|
|
||||||
#endif
|
|
||||||
//#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
|
||||||
//#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
|
|
||||||
//#endif
|
|
||||||
//#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
|
|
||||||
//#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
|
|
||||||
//#endif
|
|
||||||
#else /* LWIP_WND_SCALE */
|
|
||||||
|
|
||||||
#if ! ESP_PER_SOC_TCP_WND
|
|
||||||
#if (LWIP_TCP && (TCP_WND > 0xffff))
|
|
||||||
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_WND_SCALE */
|
|
||||||
|
|
||||||
#if ! ESP_PER_SOC_TCP_WND
|
|
||||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN(0) > 0xffff))
|
|
||||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN(0) < 2))
|
|
||||||
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
|
||||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
|
|
||||||
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_NETIF_API && (NO_SYS==1))
|
|
||||||
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
|
|
||||||
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_PPP_API && (NO_SYS==1))
|
|
||||||
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_PPP_API && (PPP_SUPPORT==0))
|
|
||||||
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
|
|
||||||
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
|
|
||||||
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (!LWIP_ARP && LWIP_AUTOIP)
|
|
||||||
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
|
|
||||||
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
|
|
||||||
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
|
|
||||||
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
|
|
||||||
#endif
|
|
||||||
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
|
||||||
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
|
||||||
#endif
|
|
||||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
|
||||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
|
||||||
#endif
|
|
||||||
#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
|
|
||||||
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
|
|
||||||
#endif
|
|
||||||
#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
|
|
||||||
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
|
|
||||||
#endif
|
|
||||||
#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
|
|
||||||
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
|
|
||||||
#endif
|
|
||||||
#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
|
|
||||||
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
|
|
||||||
#endif
|
|
||||||
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
|
||||||
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
|
||||||
#endif
|
|
||||||
#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
|
|
||||||
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
|
|
||||||
#endif
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
|
||||||
#endif
|
|
||||||
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
|
|
||||||
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
|
|
||||||
#endif
|
|
||||||
#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF
|
|
||||||
#error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues"
|
|
||||||
#endif
|
|
||||||
#if LWIP_NETCONN && LWIP_TCP
|
|
||||||
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
|
|
||||||
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
|
|
||||||
#endif
|
|
||||||
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
|
|
||||||
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
|
|
||||||
#endif
|
|
||||||
#endif /* LWIP_NETCONN && LWIP_TCP */
|
|
||||||
#if LWIP_SOCKET
|
|
||||||
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
|
|
||||||
#if SO_REUSEADDR != SOF_REUSEADDR
|
|
||||||
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
|
|
||||||
#endif
|
|
||||||
#if SO_KEEPALIVE != SOF_KEEPALIVE
|
|
||||||
#error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
|
|
||||||
#endif
|
|
||||||
#if SO_BROADCAST != SOF_BROADCAST
|
|
||||||
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
|
|
||||||
#endif
|
|
||||||
#endif /* LWIP_SOCKET */
|
|
||||||
|
|
||||||
|
|
||||||
/* Compile-time checks for deprecated options.
|
|
||||||
*/
|
|
||||||
#ifdef MEMP_NUM_TCPIP_MSG
|
|
||||||
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
|
|
||||||
#endif
|
|
||||||
#ifdef TCP_REXMIT_DEBUG
|
|
||||||
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
|
|
||||||
#endif
|
|
||||||
#ifdef RAW_STATS
|
|
||||||
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
|
|
||||||
#endif
|
|
||||||
#ifdef ETHARP_QUEUE_FIRST
|
|
||||||
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
|
|
||||||
#endif
|
|
||||||
#ifdef ETHARP_ALWAYS_INSERT
|
|
||||||
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
|
|
||||||
#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
|
|
||||||
#endif
|
|
||||||
#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
|
|
||||||
#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* MEMP sanity checks */
|
|
||||||
#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
|
|
||||||
#if LWIP_NETCONN
|
|
||||||
#if MEMP_MEM_MALLOC
|
|
||||||
#if !MEMP_NUM_NETCONN && LWIP_SOCKET
|
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
|
|
||||||
#endif
|
|
||||||
#else /* MEMP_MEM_MALLOC */
|
|
||||||
#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
|
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
|
||||||
#endif /* LWIP_NETCONN */
|
|
||||||
#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
|
|
||||||
|
|
||||||
/* TCP sanity checks */
|
|
||||||
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
|
|
||||||
#if ! ESP_PER_SOC_TCP_WND
|
|
||||||
#if LWIP_TCP
|
|
||||||
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN(0))
|
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TCP_SND_BUF(0) < (2 * TCP_MSS)
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#if TCP_SND_QUEUELEN(0) < (2 * (TCP_SND_BUF(0) / TCP_MSS))
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF(0)/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#if TCP_SNDLOWAT >= TCP_SND_BUF(0)
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
|
|
||||||
#endif
|
|
||||||
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN(0)
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
|
|
||||||
#error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ! ESP_LWIP
|
|
||||||
#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TCP_WND < TCP_MSS
|
|
||||||
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize all modules.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
lwip_init(void)
|
|
||||||
{
|
|
||||||
/* Modules initialization */
|
|
||||||
stats_init();
|
|
||||||
#if !NO_SYS
|
|
||||||
sys_init();
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
mem_init();
|
|
||||||
memp_init();
|
|
||||||
pbuf_init();
|
|
||||||
netif_init();
|
|
||||||
#if LWIP_IPV4
|
|
||||||
ip_init();
|
|
||||||
#if LWIP_ARP
|
|
||||||
etharp_init();
|
|
||||||
#endif /* LWIP_ARP */
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#if LWIP_RAW
|
|
||||||
raw_init();
|
|
||||||
#endif /* LWIP_RAW */
|
|
||||||
#if LWIP_UDP
|
|
||||||
udp_init();
|
|
||||||
#endif /* LWIP_UDP */
|
|
||||||
#if LWIP_TCP
|
|
||||||
tcp_init();
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if LWIP_AUTOIP
|
|
||||||
autoip_init();
|
|
||||||
#endif /* LWIP_AUTOIP */
|
|
||||||
#if LWIP_IGMP
|
|
||||||
igmp_init();
|
|
||||||
#endif /* LWIP_IGMP */
|
|
||||||
#if LWIP_DNS
|
|
||||||
dns_init();
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
#if PPP_SUPPORT
|
|
||||||
ppp_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_TIMERS
|
|
||||||
sys_timeouts_init();
|
|
||||||
#endif /* LWIP_TIMERS */
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
/**
|
|
||||||
* @file ip.c
|
|
||||||
* Common IPv4 and IPv6 code
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if LWIP_IPV4 || LWIP_IPV6
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
|
|
||||||
/** Global data for both IPv4 and IPv6 */
|
|
||||||
struct ip_globals ip_data;
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
|
|
||||||
const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
|
|
||||||
|
|
||||||
/** Convert IP address string (both versions) to numeric.
|
|
||||||
* The version is auto-detected from the string.
|
|
||||||
*
|
|
||||||
* @param cp IP address string to convert
|
|
||||||
* @param addr conversion result is stored here
|
|
||||||
* @return 1 on success, 0 on error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
ipaddr_aton(const char *cp, ip_addr_t *addr)
|
|
||||||
{
|
|
||||||
if (cp != NULL) {
|
|
||||||
const char* c;
|
|
||||||
for (c = cp; *c != 0; c++) {
|
|
||||||
if (*c == ':') {
|
|
||||||
/* contains a colon: IPv6 address */
|
|
||||||
if (addr) {
|
|
||||||
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
|
|
||||||
}
|
|
||||||
return ip6addr_aton(cp, ip_2_ip6(addr));
|
|
||||||
} else if (*c == '.') {
|
|
||||||
/* contains a dot: IPv4 address */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* call ip4addr_aton as fallback or if IPv4 was found */
|
|
||||||
if (addr) {
|
|
||||||
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
|
|
||||||
}
|
|
||||||
return ip4addr_aton(cp, ip_2_ip4(addr));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If both IP versions are enabled, this function can dispatch packets to the correct one. */
|
|
||||||
err_t
|
|
||||||
ip_input(struct pbuf *p, struct netif *inp)
|
|
||||||
{
|
|
||||||
if (p != NULL) {
|
|
||||||
if (IP_HDR_GET_VERSION(p->payload) == 6) {
|
|
||||||
return ip6_input(p, inp);
|
|
||||||
}
|
|
||||||
return ip4_input(p, inp);
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 || LWIP_IPV6 */
|
|
|
@ -1,551 +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_IPV4 && 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 "lwip/dhcp.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, ip4_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, ip4_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, ðbroadcast,
|
|
||||||
(struct eth_addr *)netif->hwaddr, IP4_ADDR_ANY, ðzero,
|
|
||||||
&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, ðbroadcast,
|
|
||||||
(struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero,
|
|
||||||
&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;
|
|
||||||
ip4_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_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
|
|
||||||
/* interface is used by routing now that an address is set */
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
struct dhcp *dhcp = netif->dhcp;
|
|
||||||
if (dhcp->cb != NULL) {
|
|
||||||
dhcp->cb(netif);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
|
|
||||||
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
|
|
||||||
|
|
||||||
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
|
|
||||||
* ARP Packets are formed correctly
|
|
||||||
*/
|
|
||||||
netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
|
|
||||||
|
|
||||||
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;
|
|
||||||
ip4_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
|
|
||||||
* chosen 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
|
|
||||||
* acquiring 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) {
|
|
||||||
autoip_start_probing(netif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop AutoIP client
|
|
||||||
*
|
|
||||||
* @param netif network interface on which stop the AutoIP client
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
autoip_stop(struct netif *netif)
|
|
||||||
{
|
|
||||||
if (netif->autoip) {
|
|
||||||
netif->autoip->state = AUTOIP_STATE_OFF;
|
|
||||||
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
|
|
||||||
netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
autoip_tmr(void)
|
|
||||||
{
|
|
||||||
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_addr. 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;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* nothing to do in other states */
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
ip4_addr_t sipaddr, dipaddr;
|
|
||||||
struct eth_addr netifaddr;
|
|
||||||
ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
|
|
||||||
|
|
||||||
/* Copy struct ip4_addr2 to aligned ip4_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 ((ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
|
|
||||||
(ip4_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 (ip4_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** check if AutoIP supplied netif->ip_addr
|
|
||||||
*
|
|
||||||
* @param netif the netif to check
|
|
||||||
* @return 1 if AutoIP supplied netif->ip_addr (state BOUND),
|
|
||||||
* 0 otherwise
|
|
||||||
*/
|
|
||||||
u8_t
|
|
||||||
autoip_supplied_address(struct netif *netif)
|
|
||||||
{
|
|
||||||
if ((netif != NULL) && (netif->autoip != NULL)) {
|
|
||||||
if (netif->autoip->state == AUTOIP_STATE_BOUND) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_AUTOIP */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,386 +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_IPV4 && 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 <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 icmp 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;
|
|
||||||
const struct ip_hdr *iphdr_in;
|
|
||||||
s16_t hlen;
|
|
||||||
const ip4_addr_t* src;
|
|
||||||
|
|
||||||
ICMP_STATS_INC(icmp.recv);
|
|
||||||
MIB2_STATS_INC(mib2.icmpinmsgs);
|
|
||||||
|
|
||||||
iphdr_in = ip4_current_header();
|
|
||||||
hlen = IPH_HL(iphdr_in) * 4;
|
|
||||||
if (p->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). */
|
|
||||||
MIB2_STATS_INC(mib2.icmpinechoreps);
|
|
||||||
break;
|
|
||||||
case ICMP_ECHO:
|
|
||||||
MIB2_STATS_INC(mib2.icmpinechos);
|
|
||||||
src = ip4_current_dest_addr();
|
|
||||||
/* multicast destination address? */
|
|
||||||
if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
|
|
||||||
#if LWIP_MULTICAST_PING
|
|
||||||
/* For multicast, use address of receiving interface as source address */
|
|
||||||
src = netif_ip4_addr(inp);
|
|
||||||
#else /* LWIP_MULTICAST_PING */
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n"));
|
|
||||||
goto icmperr;
|
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
|
||||||
}
|
|
||||||
/* broadcast destination address? */
|
|
||||||
if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) {
|
|
||||||
#if LWIP_BROADCAST_PING
|
|
||||||
/* For broadcast, use address of receiving interface as source address */
|
|
||||||
src = netif_ip4_addr(inp);
|
|
||||||
#else /* LWIP_BROADCAST_PING */
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n"));
|
|
||||||
goto icmperr;
|
|
||||||
#endif /* 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 CHECKSUM_CHECK_ICMP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
|
|
||||||
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);
|
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
|
||||||
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
|
||||||
/* p is not big enough to contain link headers
|
|
||||||
* allocate a new one and copy p into it
|
|
||||||
*/
|
|
||||||
struct pbuf *r;
|
|
||||||
/* allocate new packet buffer with space for link headers */
|
|
||||||
r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM);
|
|
||||||
if (r == NULL) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
|
|
||||||
goto icmperr;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("check that first pbuf can hold struct the ICMP header",
|
|
||||||
(r->len >= hlen + sizeof(struct icmp_echo_hdr)));
|
|
||||||
/* copy the ip header */
|
|
||||||
MEMCPY(r->payload, iphdr_in, hlen);
|
|
||||||
/* switch r->payload back to icmp header */
|
|
||||||
if (pbuf_header(r, -hlen)) {
|
|
||||||
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
|
||||||
pbuf_free(r);
|
|
||||||
goto icmperr;
|
|
||||||
}
|
|
||||||
/* copy the rest of the packet without ip header */
|
|
||||||
if (pbuf_copy(r, p) != ERR_OK) {
|
|
||||||
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
|
|
||||||
pbuf_free(r);
|
|
||||||
goto icmperr;
|
|
||||||
}
|
|
||||||
/* 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 + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
|
||||||
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
|
||||||
goto icmperr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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;
|
|
||||||
if (pbuf_header(p, hlen)) {
|
|
||||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
|
||||||
} else {
|
|
||||||
err_t ret;
|
|
||||||
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
|
|
||||||
ip4_addr_copy(iphdr->src, *src);
|
|
||||||
ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
|
|
||||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
|
||||||
#if CHECKSUM_GEN_ICMP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
|
||||||
else {
|
|
||||||
iecho->chksum = 0;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
|
||||||
#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
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_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 */
|
|
||||||
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
|
||||||
/* increase number of echo replies attempted to send */
|
|
||||||
MIB2_STATS_INC(mib2.icmpoutechoreps);
|
|
||||||
|
|
||||||
/* send an ICMP packet */
|
|
||||||
ret = ip4_output_if(p, src, 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: %s\n", lwip_strerr(ret)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (type == ICMP_DUR) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
|
||||||
} else if (type == ICMP_TE) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
|
||||||
} else if (type == ICMP_PP) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
|
||||||
} else if (type == ICMP_SQ) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpinsrcquenchs);
|
|
||||||
} else if (type == ICMP_RD) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpinredirects);
|
|
||||||
} else if (type == ICMP_TS) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpintimestamps);
|
|
||||||
} else if (type == ICMP_TSR) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpintimestampreps);
|
|
||||||
} else if (type == ICMP_AM) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpinaddrmasks);
|
|
||||||
} else if (type == ICMP_AMR) {
|
|
||||||
MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
|
||||||
return;
|
|
||||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
|
||||||
icmperr:
|
|
||||||
pbuf_free(p);
|
|
||||||
ICMP_STATS_INC(icmp.err);
|
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
|
||||||
return;
|
|
||||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
MIB2_STATS_INC(mib2.icmpoutdestunreachs);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
MIB2_STATS_INC(mib2.icmpouttimeexcds);
|
|
||||||
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;
|
|
||||||
ip4_addr_t iphdr_src;
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* increase number of messages attempted to send */
|
|
||||||
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
|
||||||
|
|
||||||
/* 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"));
|
|
||||||
MIB2_STATS_INC(mib2.icmpouterrors);
|
|
||||||
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 "));
|
|
||||||
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
|
||||||
ip4_addr_debug_print_val(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);
|
|
||||||
|
|
||||||
ip4_addr_copy(iphdr_src, iphdr->src);
|
|
||||||
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
|
|
||||||
{
|
|
||||||
ip4_addr_t iphdr_dst;
|
|
||||||
ip4_addr_copy(iphdr_dst, iphdr->dest);
|
|
||||||
netif = ip4_route_src(&iphdr_src, &iphdr_dst);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
netif = ip4_route(&iphdr_src);
|
|
||||||
#endif
|
|
||||||
if (netif != NULL) {
|
|
||||||
/* calculate checksum */
|
|
||||||
icmphdr->chksum = 0;
|
|
||||||
#if CHECKSUM_GEN_ICMP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
|
|
||||||
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
|
||||||
ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
|
|
||||||
}
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_ICMP */
|
|
|
@ -1,827 +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_IPV4 && 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/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_FLD_8(u8_t igmp_msgtype);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t igmp_maxresp);
|
|
||||||
PACK_STRUCT_FIELD(u16_t igmp_checksum);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_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, const ip4_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, const ip4_addr_t *src, const ip4_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 ip4_addr_t allsystems;
|
|
||||||
static ip4_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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", (void*)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 "));
|
|
||||||
ip4_addr_debug_print_val(IGMP_DEBUG, allsystems);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)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 "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, &group->group_address);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)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", (void*)netif));
|
|
||||||
|
|
||||||
while (group != NULL) {
|
|
||||||
if ((group->netif == netif) && (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
|
|
||||||
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, const ip4_addr_t *addr)
|
|
||||||
{
|
|
||||||
struct igmp_group *group = igmp_group_list;
|
|
||||||
|
|
||||||
while (group != NULL) {
|
|
||||||
if ((group->netif == ifp) && (ip4_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, const ip4_addr_t *addr)
|
|
||||||
{
|
|
||||||
struct igmp_group *group;
|
|
||||||
/* 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;
|
|
||||||
ip4_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 ")));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, addr);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)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 igmp 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, const ip4_addr_t *dest)
|
|
||||||
{
|
|
||||||
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 */
|
|
||||||
if (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 "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src));
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest));
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)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 ((ip4_addr_cmp(dest, &allsystems)) && ip4_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) && (!(ip4_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 (!ip4_addr_isany(&igmp->igmp_group_address)) {
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
|
|
||||||
if (ip4_addr_cmp(dest, &allsystems)) {
|
|
||||||
ip4_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 */
|
|
||||||
ip4_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, (void*)&group, (void*)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(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
err_t err = ERR_VAL; /* no matching interface */
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* make sure it is multicast address */
|
|
||||||
LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
|
|
||||||
LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_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) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
|
|
||||||
err = igmp_joingroup_netif(netif, groupaddr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
/* Return an error even if some network interfaces are joined */
|
|
||||||
/** @todo undo any other netif already joined */
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* proceed to next network interface */
|
|
||||||
netif = netif->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join a group on one network interface.
|
|
||||||
*
|
|
||||||
* @param netif 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, an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
struct igmp_group *group;
|
|
||||||
|
|
||||||
/* make sure it is multicast address */
|
|
||||||
LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
|
|
||||||
LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
|
|
||||||
|
|
||||||
/* make sure it is an igmp-enabled netif */
|
|
||||||
LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
|
|
||||||
|
|
||||||
/* 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_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
|
|
||||||
} else {
|
|
||||||
/* OK - it was new group */
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: "));
|
|
||||||
ip4_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_netif: igmp_mac_filter(ADD "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)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 */
|
|
||||||
return ERR_OK;
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n"));
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
err_t err = ERR_VAL; /* no matching interface */
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* make sure it is multicast address */
|
|
||||||
LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
|
|
||||||
LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_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) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
|
|
||||||
err_t res = igmp_leavegroup_netif(netif, groupaddr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
/* Store this result if we have not yet gotten a success */
|
|
||||||
err = res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* proceed to next network interface */
|
|
||||||
netif = netif->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leave a group on one network interface.
|
|
||||||
*
|
|
||||||
* @param netif 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, an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
struct igmp_group *group;
|
|
||||||
|
|
||||||
/* make sure it is multicast address */
|
|
||||||
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
|
|
||||||
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
|
|
||||||
|
|
||||||
/* make sure it is an igmp-enabled netif */
|
|
||||||
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
|
|
||||||
|
|
||||||
/* 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_netif: Leaving group: "));
|
|
||||||
ip4_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_netif: 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_netif: igmp_mac_filter(DEL "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
|
|
||||||
netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: remove group: "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
|
|
||||||
|
|
||||||
/* Free the group */
|
|
||||||
igmp_remove_group(group);
|
|
||||||
} else {
|
|
||||||
/* Decrement group use */
|
|
||||||
group->use--;
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n"));
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
(unless it is the allsystems group) */
|
|
||||||
if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
|
|
||||||
(!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
|
|
||||||
ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address));
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)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)
|
|
||||||
{
|
|
||||||
#ifdef LWIP_RAND
|
|
||||||
group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1;
|
|
||||||
#else /* LWIP_RAND */
|
|
||||||
/* ATTENTION: use this only if absolutely necessary! */
|
|
||||||
group->timer = max_time / 2;
|
|
||||||
#endif /* LWIP_RAND */
|
|
||||||
|
|
||||||
if (group->timer == 0) {
|
|
||||||
group->timer = 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, const ip4_addr_t *src, const ip4_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 ip4_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;
|
|
||||||
ip4_addr_t src = *IP4_ADDR_ANY;
|
|
||||||
ip4_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)));
|
|
||||||
ip4_addr_copy(src, *netif_ip4_addr(group->netif));
|
|
||||||
|
|
||||||
if (type == IGMP_V2_MEMB_REPORT) {
|
|
||||||
dest = &(group->group_address);
|
|
||||||
ip4_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;
|
|
||||||
ip4_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_IPV4 && LWIP_IGMP */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,362 +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"
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#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 = IPADDR4_INIT(IPADDR_ANY);
|
|
||||||
const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(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 ESP_IRAM_ATTR
|
|
||||||
ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif)
|
|
||||||
{
|
|
||||||
ip4_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_ip4_addr(netif))) {
|
|
||||||
return 0;
|
|
||||||
/* on the same (sub) network... */
|
|
||||||
} else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif))
|
|
||||||
/* ...and host identifier bits are all ones? =>... */
|
|
||||||
&& ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) ==
|
|
||||||
(IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) {
|
|
||||||
/* => 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 representation (e.g. "127.0.0.1")
|
|
||||||
* @return ip address in network order
|
|
||||||
*/
|
|
||||||
u32_t
|
|
||||||
ipaddr_addr(const char *cp)
|
|
||||||
{
|
|
||||||
ip4_addr_t val;
|
|
||||||
|
|
||||||
if (ip4addr_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 representation (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
|
|
||||||
ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
|
||||||
{
|
|
||||||
u32_t val;
|
|
||||||
u8_t base;
|
|
||||||
char c;
|
|
||||||
u32_t parts[4];
|
|
||||||
u32_t *pp = parts;
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
//#if 0
|
|
||||||
char ch;
|
|
||||||
unsigned long cutoff;
|
|
||||||
int cutlim;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ESP_IP4_ATON
|
|
||||||
cutoff =(unsigned long)0xffffffff / (unsigned long)base;
|
|
||||||
cutlim =(unsigned long)0xffffffff % (unsigned long)base;
|
|
||||||
for (;;) {
|
|
||||||
if (isdigit(c)) {
|
|
||||||
ch = (int)(c - '0');
|
|
||||||
if (val > cutoff || (val == cutoff && ch > cutlim))
|
|
||||||
return (0);
|
|
||||||
val = (val * base) + (int)(c - '0');
|
|
||||||
c = *++cp;
|
|
||||||
} else if (base == 16 && isxdigit(c)) {
|
|
||||||
ch = (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
|
||||||
if (val > cutoff || (val == cutoff && ch > cutlim))
|
|
||||||
return (0);
|
|
||||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
|
||||||
c = *++cp;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (parts[0] > 0xff) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
val |= parts[0] << 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: /* a.b.c -- 8.8.16 bits */
|
|
||||||
if (val > 0xffff) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 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
|
|
||||||
* representation of addr
|
|
||||||
*/
|
|
||||||
char*
|
|
||||||
ip4addr_ntoa(const ip4_addr_t *addr)
|
|
||||||
{
|
|
||||||
static char str[IP4ADDR_STRLEN_MAX];
|
|
||||||
return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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*
|
|
||||||
ip4addr_ntoa_r(const ip4_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
|
@ -1,897 +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"
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#include "lwip/ip_frag.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/inet_chksum.h"
|
|
||||||
#include "lwip/netif.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) \
|
|
||||||
(ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \
|
|
||||||
ip4_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
MIB2_STATS_INC(mib2.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, *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;
|
|
||||||
oldest_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;
|
|
||||||
oldest_prev = prev;
|
|
||||||
} else if (r->timer <= oldest->timer) {
|
|
||||||
/* older than the previous oldest */
|
|
||||||
oldest = r;
|
|
||||||
oldest_prev = prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (r->next != NULL) {
|
|
||||||
prev = r;
|
|
||||||
}
|
|
||||||
r = r->next;
|
|
||||||
}
|
|
||||||
if (oldest != NULL) {
|
|
||||||
pbufs_freed_current = ip_reass_free_complete_datagram(oldest, 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;
|
|
||||||
#if ! IP_REASS_FREE_OLDEST
|
|
||||||
LWIP_UNUSED_ARG(clen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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_reassdata 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 one 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 holes. */
|
|
||||||
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 holes so far */
|
|
||||||
if (valid) {
|
|
||||||
/* then check if the rest of the fragments is here */
|
|
||||||
/* Check if the queue starts with the first datagram */
|
|
||||||
if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) {
|
|
||||||
valid = 0;
|
|
||||||
} else {
|
|
||||||
/* and check that there are no holes 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 *
|
|
||||||
ip4_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;
|
|
||||||
|
|
||||||
IPFRAG_STATS_INC(ip_frag.recv);
|
|
||||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
|
||||||
|
|
||||||
fraghdr = (struct ip_hdr*)p->payload;
|
|
||||||
|
|
||||||
if ((IPH_HL(fraghdr) * 4) != IP_HLEN) {
|
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_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,("ip4_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, ("ip4_reass: matching previous fragment ID=%"X16_F"\n",
|
|
||||||
ntohs(IPH_ID(fraghdr))));
|
|
||||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
("ip4_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)) {
|
|
||||||
struct ip_reassdata *ipr_prev;
|
|
||||||
/* 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? */
|
|
||||||
#if CHECKSUM_GEN_IP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) {
|
|
||||||
IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_GEN_IP */
|
|
||||||
|
|
||||||
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 succeeding fragment */
|
|
||||||
pbuf_header(r, -IP_HLEN);
|
|
||||||
pbuf_cat(p, r);
|
|
||||||
r = iprh->next_pbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the previous entry in the linked list */
|
|
||||||
if (ipr == reassdatagrams) {
|
|
||||||
ipr_prev = NULL;
|
|
||||||
} else {
|
|
||||||
for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
|
|
||||||
if (ipr_prev->next == ipr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
MIB2_STATS_INC(mib2.ipreasmoks);
|
|
||||||
|
|
||||||
/* 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,("ip4_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
|
|
||||||
ip4_frag(struct pbuf *p, struct netif *netif, const ip4_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"));
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
/* fill in the IP header */
|
|
||||||
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
|
|
||||||
iphdr = (struct ip_hdr*)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) {
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
/* 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);
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
#if CHECKSUM_GEN_IP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
|
|
||||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_GEN_IP */
|
|
||||||
|
|
||||||
#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);
|
|
||||||
MIB2_STATS_INC(mib2.ipfragcreates);
|
|
||||||
pbuf_free(header);
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n"));
|
|
||||||
pbuf_free(rambuf);
|
|
||||||
goto memerr;
|
|
||||||
}
|
|
||||||
#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 */
|
|
||||||
MIB2_STATS_INC(mib2.ipfragoks);
|
|
||||||
return ERR_OK;
|
|
||||||
memerr:
|
|
||||||
MIB2_STATS_INC(mib2.ipfragfails);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
#endif /* IP_FRAG */
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
|
@ -1 +0,0 @@
|
||||||
IPv6 support in lwIP is very experimental.
|
|
|
@ -1,50 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* DHCPv6.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */
|
|
|
@ -1,159 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_ETHERNET
|
|
||||||
|
|
||||||
#include "lwip/ethip6.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/inet_chksum.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/icmp6.h"
|
|
||||||
#include "netif/ethernet.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an IPv6 packet on the network using netif->linkoutput
|
|
||||||
* The ethernet header is filled in before sending.
|
|
||||||
*
|
|
||||||
* @params netif the lwIP network interface on which to send the packet
|
|
||||||
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
|
||||||
* @params src the source MAC address to be copied into the ethernet header
|
|
||||||
* @params dst the destination MAC address to be copied into the ethernet header
|
|
||||||
* @return ERR_OK if the packet was sent, any other err_t on failure
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
|
||||||
{
|
|
||||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
|
||||||
|
|
||||||
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
|
||||||
(netif->hwaddr_len == 6));
|
|
||||||
SMEMCPY(ðhdr->dest, dst, 6);
|
|
||||||
SMEMCPY(ðhdr->src, src, 6);
|
|
||||||
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
|
||||||
/* send the packet */
|
|
||||||
return netif->linkoutput(netif, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
|
||||||
*
|
|
||||||
* For IPv6 multicast, corresponding Ethernet addresses
|
|
||||||
* are selected and the packet is transmitted on the link.
|
|
||||||
*
|
|
||||||
* For unicast addresses, ...
|
|
||||||
*
|
|
||||||
* @TODO anycast addresses
|
|
||||||
*
|
|
||||||
* @param netif The lwIP network interface which the IP packet will be sent on.
|
|
||||||
* @param q The pbuf(s) containing the IP packet to be sent.
|
|
||||||
* @param ip6addr The IP address of the packet destination.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
|
||||||
* or the return type of either etharp_query() or etharp_send_ip().
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
|
||||||
{
|
|
||||||
struct eth_addr dest;
|
|
||||||
s8_t i;
|
|
||||||
|
|
||||||
/* make room for Ethernet header - should not fail */
|
|
||||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
|
||||||
/* bail out */
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
|
||||||
("etharp_output: could not allocate room for header.\n"));
|
|
||||||
return ERR_BUF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* multicast destination IP address? */
|
|
||||||
if (ip6_addr_ismulticast(ip6addr)) {
|
|
||||||
/* Hash IP multicast address to MAC address.*/
|
|
||||||
dest.addr[0] = 0x33;
|
|
||||||
dest.addr[1] = 0x33;
|
|
||||||
dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0];
|
|
||||||
dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1];
|
|
||||||
dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2];
|
|
||||||
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
|
||||||
|
|
||||||
/* Send out. */
|
|
||||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have a unicast destination IP address */
|
|
||||||
/* TODO anycast? */
|
|
||||||
/* Get next hop record. */
|
|
||||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
|
||||||
if (i < 0) {
|
|
||||||
/* failed to get a next hop neighbor record. */
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now that we have a destination record, send or queue the packet. */
|
|
||||||
if (neighbor_cache[i].state == ND6_STALE) {
|
|
||||||
/* Switch to delay state. */
|
|
||||||
neighbor_cache[i].state = ND6_DELAY;
|
|
||||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
|
||||||
}
|
|
||||||
/* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */
|
|
||||||
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
|
|
||||||
(neighbor_cache[i].state == ND6_DELAY) ||
|
|
||||||
(neighbor_cache[i].state == ND6_PROBE)) {
|
|
||||||
|
|
||||||
/* Send out. */
|
|
||||||
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
|
|
||||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should queue packet on this interface. */
|
|
||||||
pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR);
|
|
||||||
return nd6_queue_packet(i, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
|
|
@ -1,349 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 version of ICMP, as per RFC 4443.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/icmp6.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/inet_chksum.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifndef LWIP_ICMP6_DATASIZE
|
|
||||||
#define LWIP_ICMP6_DATASIZE 8
|
|
||||||
#endif
|
|
||||||
#if LWIP_ICMP6_DATASIZE == 0
|
|
||||||
#define LWIP_ICMP6_DATASIZE 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Forward declarations */
|
|
||||||
static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an input ICMPv6 message. Called by ip6_input.
|
|
||||||
*
|
|
||||||
* Will generate a reply for echo requests. Other messages are forwarded
|
|
||||||
* to nd6_input, or mld6_input.
|
|
||||||
*
|
|
||||||
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
|
||||||
* @param inp the netif on which this packet was received
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
icmp6_input(struct pbuf *p, struct netif *inp)
|
|
||||||
{
|
|
||||||
struct icmp6_hdr *icmp6hdr;
|
|
||||||
struct pbuf * r;
|
|
||||||
const ip6_addr_t * reply_src;
|
|
||||||
|
|
||||||
ICMP6_STATS_INC(icmp6.recv);
|
|
||||||
|
|
||||||
/* Check that ICMPv6 header fits in payload */
|
|
||||||
if (p->len < sizeof(struct icmp6_hdr)) {
|
|
||||||
/* drop short packets */
|
|
||||||
pbuf_free(p);
|
|
||||||
ICMP6_STATS_INC(icmp6.lenerr);
|
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
|
||||||
|
|
||||||
#if CHECKSUM_CHECK_ICMP6
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) {
|
|
||||||
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
|
|
||||||
ip6_current_dest_addr()) != 0) {
|
|
||||||
/* Checksum failed */
|
|
||||||
pbuf_free(p);
|
|
||||||
ICMP6_STATS_INC(icmp6.chkerr);
|
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_CHECK_ICMP6 */
|
|
||||||
|
|
||||||
switch (icmp6hdr->type) {
|
|
||||||
case ICMP6_TYPE_NA: /* Neighbor advertisement */
|
|
||||||
case ICMP6_TYPE_NS: /* Neighbor solicitation */
|
|
||||||
case ICMP6_TYPE_RA: /* Router advertisement */
|
|
||||||
case ICMP6_TYPE_RD: /* Redirect */
|
|
||||||
case ICMP6_TYPE_PTB: /* Packet too big */
|
|
||||||
nd6_input(p, inp);
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
case ICMP6_TYPE_RS:
|
|
||||||
#if LWIP_IPV6_FORWARD
|
|
||||||
/* TODO implement router functionality */
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
case ICMP6_TYPE_MLQ:
|
|
||||||
case ICMP6_TYPE_MLR:
|
|
||||||
case ICMP6_TYPE_MLD:
|
|
||||||
mld6_input(p, inp);
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case ICMP6_TYPE_EREQ:
|
|
||||||
#if !LWIP_MULTICAST_PING
|
|
||||||
/* multicast destination address? */
|
|
||||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(p);
|
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
|
||||||
|
|
||||||
/* Allocate reply. */
|
|
||||||
r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
|
|
||||||
if (r == NULL) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(p);
|
|
||||||
ICMP6_STATS_INC(icmp6.memerr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy echo request. */
|
|
||||||
if (pbuf_copy(r, p) != ERR_OK) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(p);
|
|
||||||
pbuf_free(r);
|
|
||||||
ICMP6_STATS_INC(icmp6.err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine reply source IPv6 address. */
|
|
||||||
#if LWIP_MULTICAST_PING
|
|
||||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
|
||||||
reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr()));
|
|
||||||
if (reply_src == NULL) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(p);
|
|
||||||
pbuf_free(r);
|
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
|
||||||
{
|
|
||||||
reply_src = ip6_current_dest_addr();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set fields in reply. */
|
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
|
||||||
#if CHECKSUM_GEN_ICMP6
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) {
|
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
|
||||||
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_GEN_ICMP6 */
|
|
||||||
|
|
||||||
/* Send reply. */
|
|
||||||
ICMP6_STATS_INC(icmp6.xmit);
|
|
||||||
ip6_output_if(r, reply_src, ip6_current_src_addr(),
|
|
||||||
LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
|
|
||||||
pbuf_free(r);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ICMP6_STATS_INC(icmp6.proterr);
|
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an icmpv6 'destination unreachable' packet.
|
|
||||||
*
|
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
|
||||||
* p->payload pointing to the IPv6 header
|
|
||||||
* @param c ICMPv6 code for the unreachable type
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
|
||||||
{
|
|
||||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an icmpv6 'packet too big' packet.
|
|
||||||
*
|
|
||||||
* @param p the input packet for which the 'packet too big' should be sent,
|
|
||||||
* p->payload pointing to the IPv6 header
|
|
||||||
* @param mtu the maximum mtu that we can accept
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
|
||||||
{
|
|
||||||
icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an icmpv6 'time exceeded' packet.
|
|
||||||
*
|
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
|
||||||
* p->payload pointing to the IPv6 header
|
|
||||||
* @param c ICMPv6 code for the time exceeded type
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
|
||||||
{
|
|
||||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an icmpv6 'parameter problem' packet.
|
|
||||||
*
|
|
||||||
* @param p the input packet for which the 'param problem' should be sent,
|
|
||||||
* p->payload pointing to the IP header
|
|
||||||
* @param c ICMPv6 code for the param problem type
|
|
||||||
* @param pointer the pointer to the byte where the parameter is found
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
|
||||||
{
|
|
||||||
icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an ICMPv6 packet in response to an incoming packet.
|
|
||||||
*
|
|
||||||
* @param p the input packet for which the response should be sent,
|
|
||||||
* p->payload pointing to the IPv6 header
|
|
||||||
* @param code Code of the ICMPv6 header
|
|
||||||
* @param data Additional 32-bit parameter in the ICMPv6 header
|
|
||||||
* @param type Type of the ICMPv6 header
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
|
|
||||||
{
|
|
||||||
struct pbuf *q;
|
|
||||||
struct icmp6_hdr *icmp6hdr;
|
|
||||||
const ip6_addr_t *reply_src;
|
|
||||||
ip6_addr_t *reply_dest;
|
|
||||||
ip6_addr_t reply_src_local, reply_dest_local;
|
|
||||||
struct ip6_hdr *ip6hdr;
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* ICMPv6 header + IPv6 header + data */
|
|
||||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
|
|
||||||
PBUF_RAM);
|
|
||||||
if (q == NULL) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
|
||||||
ICMP6_STATS_INC(icmp6.memerr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
|
|
||||||
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
|
|
||||||
|
|
||||||
icmp6hdr = (struct icmp6_hdr *)q->payload;
|
|
||||||
icmp6hdr->type = type;
|
|
||||||
icmp6hdr->code = code;
|
|
||||||
icmp6hdr->data = data;
|
|
||||||
|
|
||||||
/* copy fields from original packet */
|
|
||||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
|
|
||||||
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
|
||||||
|
|
||||||
/* Get the destination address and netif for this ICMP message. */
|
|
||||||
if ((ip_current_netif() == NULL) ||
|
|
||||||
((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) {
|
|
||||||
/* Special case, as ip6_current_xxx is either NULL, or points
|
|
||||||
* to a different packet than the one that expired.
|
|
||||||
* We must use the addresses that are stored in the expired packet. */
|
|
||||||
ip6hdr = (struct ip6_hdr *)p->payload;
|
|
||||||
/* copy from packed address to aligned address */
|
|
||||||
ip6_addr_copy(reply_dest_local, ip6hdr->src);
|
|
||||||
ip6_addr_copy(reply_src_local, ip6hdr->dest);
|
|
||||||
reply_dest = &reply_dest_local;
|
|
||||||
reply_src = &reply_src_local;
|
|
||||||
netif = ip6_route(reply_src, reply_dest);
|
|
||||||
if (netif == NULL) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(q);
|
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
netif = ip_current_netif();
|
|
||||||
reply_dest = ip6_current_src_addr();
|
|
||||||
|
|
||||||
/* Select an address to use as source. */
|
|
||||||
reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest));
|
|
||||||
if (reply_src == NULL) {
|
|
||||||
/* drop */
|
|
||||||
pbuf_free(q);
|
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate checksum */
|
|
||||||
icmp6hdr->chksum = 0;
|
|
||||||
#if CHECKSUM_GEN_ICMP6
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
|
||||||
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
|
|
||||||
reply_src, reply_dest);
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_GEN_ICMP6 */
|
|
||||||
|
|
||||||
ICMP6_STATS_INC(icmp6.xmit);
|
|
||||||
ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
|
|
@ -1,53 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* INET v6 addresses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/inet.h"
|
|
||||||
|
|
||||||
/** This variable is initialized by the system to contain the wildcard IPv6 address.
|
|
||||||
*/
|
|
||||||
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,292 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 addresses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
* Functions for handling IPv6 addresses.
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
|
|
||||||
/* used by IP6_ADDR_ANY(6) in ip6_addr.h */
|
|
||||||
const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul);
|
|
||||||
|
|
||||||
#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')
|
|
||||||
#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether "cp" is a valid ascii representation
|
|
||||||
* of an IPv6 address and convert to a binary address.
|
|
||||||
* Returns 1 if the address is valid, 0 if not.
|
|
||||||
*
|
|
||||||
* @param cp IPv6 address in ascii representation (e.g. "FF01::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
|
|
||||||
ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
|
||||||
{
|
|
||||||
u32_t addr_index, zero_blocks, current_block_index, current_block_value;
|
|
||||||
const char * s;
|
|
||||||
|
|
||||||
/* Count the number of colons, to count the number of blocks in a "::" sequence
|
|
||||||
zero_blocks may be 1 even if there are no :: sequences */
|
|
||||||
zero_blocks = 8;
|
|
||||||
for (s = cp; *s != 0; s++) {
|
|
||||||
if (*s == ':') {
|
|
||||||
zero_blocks--;
|
|
||||||
} else if (!isxdigit(*s)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse each block */
|
|
||||||
addr_index = 0;
|
|
||||||
current_block_index = 0;
|
|
||||||
current_block_value = 0;
|
|
||||||
for (s = cp; *s != 0; s++) {
|
|
||||||
if (*s == ':') {
|
|
||||||
if (addr) {
|
|
||||||
if (current_block_index & 0x1) {
|
|
||||||
addr->addr[addr_index++] |= current_block_value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addr->addr[addr_index] = current_block_value << 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_block_index++;
|
|
||||||
current_block_value = 0;
|
|
||||||
if (current_block_index > 7) {
|
|
||||||
/* address too long! */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (s[1] == ':') {
|
|
||||||
if (s[2] == ':') {
|
|
||||||
/* invalid format: three successive colons */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
/* "::" found, set zeros */
|
|
||||||
while (zero_blocks > 0) {
|
|
||||||
zero_blocks--;
|
|
||||||
if (current_block_index & 0x1) {
|
|
||||||
addr_index++;
|
|
||||||
} else {
|
|
||||||
if (addr) {
|
|
||||||
addr->addr[addr_index] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_block_index++;
|
|
||||||
if (current_block_index > 7) {
|
|
||||||
/* address too long! */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (isxdigit(*s)) {
|
|
||||||
/* add current digit */
|
|
||||||
current_block_value = (current_block_value << 4) +
|
|
||||||
(isdigit(*s) ? *s - '0' :
|
|
||||||
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
|
|
||||||
} else {
|
|
||||||
/* unexpected digit, space? CRLF? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr) {
|
|
||||||
if (current_block_index & 0x1) {
|
|
||||||
addr->addr[addr_index++] |= current_block_value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addr->addr[addr_index] = current_block_value << 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert to network byte order. */
|
|
||||||
if (addr) {
|
|
||||||
for (addr_index = 0; addr_index < 4; addr_index++) {
|
|
||||||
addr->addr[addr_index] = htonl(addr->addr[addr_index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_block_index != 7) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert numeric IPv6 address into ASCII representation.
|
|
||||||
* returns ptr to static buffer; not reentrant!
|
|
||||||
*
|
|
||||||
* @param addr ip6 address in network order to convert
|
|
||||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
|
||||||
* representation of addr
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
ip6addr_ntoa(const ip6_addr_t *addr)
|
|
||||||
{
|
|
||||||
static char str[40];
|
|
||||||
return ip6addr_ntoa_r(addr, str, 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
|
||||||
*
|
|
||||||
* @param addr ip6 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 *
|
|
||||||
ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
|
||||||
{
|
|
||||||
u32_t current_block_index, current_block_value, next_block_value;
|
|
||||||
s32_t i;
|
|
||||||
u8_t zero_flag, empty_block_flag;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
empty_block_flag = 0; /* used to indicate a zero chain for "::' */
|
|
||||||
|
|
||||||
for (current_block_index = 0; current_block_index < 8; current_block_index++) {
|
|
||||||
/* get the current 16-bit block */
|
|
||||||
current_block_value = htonl(addr->addr[current_block_index >> 1]);
|
|
||||||
if ((current_block_index & 0x1) == 0) {
|
|
||||||
current_block_value = current_block_value >> 16;
|
|
||||||
}
|
|
||||||
current_block_value &= 0xffff;
|
|
||||||
|
|
||||||
/* Check for empty block. */
|
|
||||||
if (current_block_value == 0) {
|
|
||||||
if (current_block_index == 7) {
|
|
||||||
/* special case, we must render a ':' for the last block. */
|
|
||||||
buf[i++] = ':';
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (empty_block_flag == 0) {
|
|
||||||
/* generate empty block "::", but only if more than one contiguous zero block,
|
|
||||||
* according to current formatting suggestions RFC 5952. */
|
|
||||||
next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]);
|
|
||||||
if ((current_block_index & 0x1) == 0x01) {
|
|
||||||
next_block_value = next_block_value >> 16;
|
|
||||||
}
|
|
||||||
next_block_value &= 0xffff;
|
|
||||||
if (next_block_value == 0) {
|
|
||||||
empty_block_flag = 1;
|
|
||||||
buf[i++] = ':';
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
continue; /* move on to next block. */
|
|
||||||
}
|
|
||||||
} else if (empty_block_flag == 1) {
|
|
||||||
/* move on to next block. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (empty_block_flag == 1) {
|
|
||||||
/* Set this flag value so we don't produce multiple empty blocks. */
|
|
||||||
empty_block_flag = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_block_index > 0) {
|
|
||||||
buf[i++] = ':';
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((current_block_value & 0xf000) == 0) {
|
|
||||||
zero_flag = 1;
|
|
||||||
} else {
|
|
||||||
buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
|
|
||||||
zero_flag = 0;
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
|
|
||||||
/* do nothing */
|
|
||||||
} else {
|
|
||||||
buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
|
|
||||||
zero_flag = 0;
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
|
|
||||||
/* do nothing */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
|
|
||||||
zero_flag = 0;
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[i++] = xchar((current_block_value & 0xf));
|
|
||||||
if (i >= buflen) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[i] = 0;
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
|
@ -1,773 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 fragmentation and reassembly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/ip6_frag.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/icmp6.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
|
|
||||||
/** 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 */
|
|
||||||
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 IPv6 header, since it replaces
|
|
||||||
* the Fragment Header in memory in incoming fragments to keep
|
|
||||||
* track of the various fragments.
|
|
||||||
*/
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip6_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
|
|
||||||
|
|
||||||
/* static variables */
|
|
||||||
static struct ip6_reassdata *reassdatagrams;
|
|
||||||
static u16_t ip6_reass_pbufcount;
|
|
||||||
|
|
||||||
/* Forward declarations. */
|
|
||||||
static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr);
|
|
||||||
#if IP_REASS_FREE_OLDEST
|
|
||||||
static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed);
|
|
||||||
#endif /* IP_REASS_FREE_OLDEST */
|
|
||||||
|
|
||||||
void
|
|
||||||
ip6_reass_tmr(void)
|
|
||||||
{
|
|
||||||
struct ip6_reassdata *r, *tmp;
|
|
||||||
|
|
||||||
#if !IPV6_FRAG_COPYHEADER
|
|
||||||
LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
|
|
||||||
sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN);
|
|
||||||
#endif /* !IPV6_FRAG_COPYHEADER */
|
|
||||||
|
|
||||||
r = reassdatagrams;
|
|
||||||
while (r != NULL) {
|
|
||||||
/* Decrement the timer. Once it reaches 0,
|
|
||||||
* clean up the incomplete fragment assembly */
|
|
||||||
if (r->timer > 0) {
|
|
||||||
r->timer--;
|
|
||||||
r = r->next;
|
|
||||||
} else {
|
|
||||||
/* reassembly timed out */
|
|
||||||
tmp = r;
|
|
||||||
/* get the next pointer before freeing */
|
|
||||||
r = r->next;
|
|
||||||
/* free the helper struct and all enqueued pbufs */
|
|
||||||
ip6_reass_free_complete_datagram(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free a datagram (struct ip6_reassdata) and all its pbufs.
|
|
||||||
* Updates the total count of enqueued pbufs (ip6_reass_pbufcount),
|
|
||||||
* sends an ICMP time exceeded packet.
|
|
||||||
*
|
|
||||||
* @param ipr datagram to free
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
|
||||||
{
|
|
||||||
struct ip6_reassdata *prev;
|
|
||||||
u16_t pbufs_freed = 0;
|
|
||||||
u8_t clen;
|
|
||||||
struct pbuf *p;
|
|
||||||
struct ip6_reass_helper *iprh;
|
|
||||||
|
|
||||||
#if LWIP_ICMP6
|
|
||||||
iprh = (struct ip6_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, move back to the original ipv6 header (we are now pointing to Fragment header).
|
|
||||||
This cannot fail since we already checked when receiving this fragment. */
|
|
||||||
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) {
|
|
||||||
LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
icmp6_time_exceeded(p, ICMP6_TE_FRAG);
|
|
||||||
}
|
|
||||||
clen = pbuf_clen(p);
|
|
||||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
|
||||||
pbufs_freed += clen;
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_ICMP6 */
|
|
||||||
|
|
||||||
/* 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 ip6_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 ip6_reassdata from the list and free it. */
|
|
||||||
if (ipr == reassdatagrams) {
|
|
||||||
reassdatagrams = ipr->next;
|
|
||||||
} else {
|
|
||||||
prev = reassdatagrams;
|
|
||||||
while (prev != NULL) {
|
|
||||||
if (prev->next == ipr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = prev->next;
|
|
||||||
}
|
|
||||||
if (prev != NULL) {
|
|
||||||
prev->next = ipr->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memp_free(MEMP_IP6_REASSDATA, ipr);
|
|
||||||
|
|
||||||
/* Finally, update number of pbufs in reassembly queue */
|
|
||||||
LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
|
|
||||||
ip6_reass_pbufcount -= pbufs_freed;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IP_REASS_FREE_OLDEST
|
|
||||||
/**
|
|
||||||
* Free the oldest datagram to make room for enqueueing new fragments.
|
|
||||||
* The datagram ipr is not freed!
|
|
||||||
*
|
|
||||||
* @param ipr ip6_reassdata for the current fragment
|
|
||||||
* @param pbufs_needed number of pbufs needed to enqueue
|
|
||||||
* (used for freeing other datagrams if not enough space)
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed)
|
|
||||||
{
|
|
||||||
struct ip6_reassdata *r, *oldest;
|
|
||||||
|
|
||||||
/* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
|
|
||||||
* but don't free the current datagram! */
|
|
||||||
do {
|
|
||||||
r = oldest = reassdatagrams;
|
|
||||||
while (r != NULL) {
|
|
||||||
if (r != ipr) {
|
|
||||||
if (r->timer <= oldest->timer) {
|
|
||||||
/* older than the previous oldest */
|
|
||||||
oldest = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r = r->next;
|
|
||||||
}
|
|
||||||
if (oldest == ipr) {
|
|
||||||
/* nothing to free, ipr is the only element on the list */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (oldest != NULL) {
|
|
||||||
ip6_reass_free_complete_datagram(oldest);
|
|
||||||
}
|
|
||||||
} while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL));
|
|
||||||
}
|
|
||||||
#endif /* IP_REASS_FREE_OLDEST */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reassembles incoming IPv6 fragments into an IPv6 datagram.
|
|
||||||
*
|
|
||||||
* @param p points to the IPv6 Fragment Header
|
|
||||||
* @param len the length of the payload (after Fragment Header)
|
|
||||||
* @return NULL if reassembly is incomplete, pbuf pointing to
|
|
||||||
* IPv6 Header if reassembly is complete
|
|
||||||
*/
|
|
||||||
struct pbuf *
|
|
||||||
ip6_reass(struct pbuf *p)
|
|
||||||
{
|
|
||||||
struct ip6_reassdata *ipr, *ipr_prev;
|
|
||||||
struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
|
||||||
struct ip6_frag_hdr * frag_hdr;
|
|
||||||
u16_t offset, len;
|
|
||||||
u8_t clen, valid = 1;
|
|
||||||
struct pbuf *q;
|
|
||||||
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.recv);
|
|
||||||
|
|
||||||
LWIP_ASSERT("ip6_frag_hdr must be in the first pbuf, not chained",
|
|
||||||
(const void*)ip6_current_header() == ((u8_t*)p->payload) - IP6_HLEN);
|
|
||||||
|
|
||||||
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
|
||||||
|
|
||||||
clen = pbuf_clen(p);
|
|
||||||
|
|
||||||
offset = ntohs(frag_hdr->_fragment_offset);
|
|
||||||
|
|
||||||
/* Calculate fragment length from IPv6 payload length.
|
|
||||||
* Adjust for headers before Fragment Header.
|
|
||||||
* And finally adjust by Fragment Header length. */
|
|
||||||
len = ntohs(ip6_current_header()->_plen);
|
|
||||||
len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN);
|
|
||||||
len -= IP6_FRAG_HLEN;
|
|
||||||
|
|
||||||
/* 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_prev = NULL; 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 ((frag_hdr->_identification == ipr->identification) &&
|
|
||||||
ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) &&
|
|
||||||
ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) {
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.cachehit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ipr_prev = ipr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ipr == NULL) {
|
|
||||||
/* Enqueue a new datagram into the datagram queue */
|
|
||||||
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
|
||||||
if (ipr == NULL) {
|
|
||||||
#if IP_REASS_FREE_OLDEST
|
|
||||||
/* Make room and try again. */
|
|
||||||
ip6_reass_remove_oldest_datagram(ipr, clen);
|
|
||||||
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
|
||||||
if (ipr != NULL) {
|
|
||||||
/* re-search ipr_prev since it might have been removed */
|
|
||||||
for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
|
|
||||||
if (ipr_prev->next == ipr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif /* IP_REASS_FREE_OLDEST */
|
|
||||||
{
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(ipr, 0, sizeof(struct ip6_reassdata));
|
|
||||||
ipr->timer = IP_REASS_MAXAGE;
|
|
||||||
|
|
||||||
/* enqueue the new structure to the front of the list */
|
|
||||||
ipr->next = reassdatagrams;
|
|
||||||
reassdatagrams = ipr;
|
|
||||||
|
|
||||||
/* Use the current IPv6 header for src/dest address reference.
|
|
||||||
* Eventually, we will replace it when we get the first fragment
|
|
||||||
* (it might be this one, in any case, it is done later). */
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
|
|
||||||
#else /* IPV6_FRAG_COPYHEADER */
|
|
||||||
/* need to use the none-const pointer here: */
|
|
||||||
ipr->iphdr = ip_data.current_ip6_header;
|
|
||||||
#endif /* IPV6_FRAG_COPYHEADER */
|
|
||||||
|
|
||||||
/* copy the fragmented packet id. */
|
|
||||||
ipr->identification = frag_hdr->_identification;
|
|
||||||
|
|
||||||
/* copy the nexth field */
|
|
||||||
ipr->nexth = frag_hdr->_nexth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we are allowed to enqueue more datagrams. */
|
|
||||||
if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
|
|
||||||
#if IP_REASS_FREE_OLDEST
|
|
||||||
ip6_reass_remove_oldest_datagram(ipr, clen);
|
|
||||||
if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) {
|
|
||||||
/* re-search ipr_prev since it might have been removed */
|
|
||||||
for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
|
|
||||||
if (ipr_prev->next == ipr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif /* IP_REASS_FREE_OLDEST */
|
|
||||||
{
|
|
||||||
/* @todo: send ICMPv6 time exceeded here? */
|
|
||||||
/* drop this pbuf */
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overwrite Fragment Header with our own helper struct. */
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
if (IPV6_FRAG_REQROOM > 0) {
|
|
||||||
/* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4).
|
|
||||||
This cannot fail since we already checked when receiving this fragment. */
|
|
||||||
err_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
|
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK);
|
|
||||||
}
|
|
||||||
#else /* IPV6_FRAG_COPYHEADER */
|
|
||||||
LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
|
|
||||||
sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN);
|
|
||||||
#endif /* IPV6_FRAG_COPYHEADER */
|
|
||||||
iprh = (struct ip6_reass_helper *)p->payload;
|
|
||||||
iprh->next_pbuf = NULL;
|
|
||||||
iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
|
|
||||||
iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
|
|
||||||
|
|
||||||
/* find the right place to insert this pbuf */
|
|
||||||
/* 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 ip6_reass_helper*)q->payload;
|
|
||||||
if (iprh->start < iprh_tmp->start) {
|
|
||||||
#if IP_REASS_CHECK_OVERLAP
|
|
||||||
if (iprh->end > iprh_tmp->start) {
|
|
||||||
/* fragment overlaps with following, throw away */
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
}
|
|
||||||
if (iprh_prev != NULL) {
|
|
||||||
if (iprh->start < iprh_prev->end) {
|
|
||||||
/* fragment overlaps with previous, throw away */
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
|
||||||
/* the new pbuf should be inserted before this */
|
|
||||||
iprh->next_pbuf = q;
|
|
||||||
if (iprh_prev != NULL) {
|
|
||||||
/* not the fragment with the lowest offset */
|
|
||||||
iprh_prev->next_pbuf = p;
|
|
||||||
} else {
|
|
||||||
/* fragment with the lowest offset */
|
|
||||||
ipr->p = p;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (iprh->start == iprh_tmp->start) {
|
|
||||||
/* received the same datagram twice: no need to keep the datagram */
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
#if IP_REASS_CHECK_OVERLAP
|
|
||||||
} else if (iprh->start < iprh_tmp->end) {
|
|
||||||
/* overlap: no need to keep the new datagram */
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
|
||||||
goto nullreturn;
|
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
|
||||||
} else {
|
|
||||||
/* Check if the fragments received so far have no gaps. */
|
|
||||||
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 = 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 = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
ip6_reass_pbufcount += clen;
|
|
||||||
|
|
||||||
/* Remember IPv6 header if this is the first fragment. */
|
|
||||||
if (iprh->start == 0) {
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
if (iprh->next_pbuf != NULL) {
|
|
||||||
MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
|
|
||||||
}
|
|
||||||
#else /* IPV6_FRAG_COPYHEADER */
|
|
||||||
/* need to use the none-const pointer here: */
|
|
||||||
ipr->iphdr = ip_data.current_ip6_header;
|
|
||||||
#endif /* IPV6_FRAG_COPYHEADER */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is the last fragment, calculate total packet length. */
|
|
||||||
if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
|
|
||||||
ipr->datagram_len = iprh->end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Additional validity tests: we have received first and last fragment. */
|
|
||||||
iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload;
|
|
||||||
if (iprh_tmp->start != 0) {
|
|
||||||
valid = 0;
|
|
||||||
}
|
|
||||||
if (ipr->datagram_len == 0) {
|
|
||||||
valid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Final validity test: no gaps between current and last fragment. */
|
|
||||||
iprh_prev = iprh;
|
|
||||||
q = iprh->next_pbuf;
|
|
||||||
while ((q != NULL) && valid) {
|
|
||||||
iprh = (struct ip6_reass_helper*)q->payload;
|
|
||||||
if (iprh_prev->end != iprh->start) {
|
|
||||||
valid = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iprh_prev = iprh;
|
|
||||||
q = iprh->next_pbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
/* All fragments have been received */
|
|
||||||
struct ip6_hdr* iphdr_ptr;
|
|
||||||
|
|
||||||
/* chain together the pbufs contained within the ip6_reassdata list. */
|
|
||||||
iprh = (struct ip6_reass_helper*) ipr->p->payload;
|
|
||||||
while (iprh != NULL) {
|
|
||||||
struct pbuf* next_pbuf = iprh->next_pbuf;
|
|
||||||
if (next_pbuf != NULL) {
|
|
||||||
/* Save next helper struct (will be hidden in next step). */
|
|
||||||
iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload;
|
|
||||||
|
|
||||||
/* hide the fragment header for every succeeding fragment */
|
|
||||||
pbuf_header(next_pbuf, -IP6_FRAG_HLEN);
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
if (IPV6_FRAG_REQROOM > 0) {
|
|
||||||
/* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */
|
|
||||||
err_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
|
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
pbuf_cat(ipr->p, next_pbuf);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iprh_tmp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
iprh = iprh_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
if (IPV6_FRAG_REQROOM > 0) {
|
|
||||||
/* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */
|
|
||||||
err_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
|
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK);
|
|
||||||
}
|
|
||||||
iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
|
|
||||||
MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN);
|
|
||||||
#else
|
|
||||||
iphdr_ptr = ipr->iphdr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Adjust datagram length by adding header lengths. */
|
|
||||||
ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr)
|
|
||||||
+ IP6_FRAG_HLEN
|
|
||||||
- IP6_HLEN);
|
|
||||||
|
|
||||||
/* Set payload length in ip header. */
|
|
||||||
iphdr_ptr->_plen = htons(ipr->datagram_len);
|
|
||||||
|
|
||||||
/* Get the first pbuf. */
|
|
||||||
p = ipr->p;
|
|
||||||
|
|
||||||
/* Restore Fragment Header in first pbuf. Mark as "single fragment"
|
|
||||||
* packet. Restore nexth. */
|
|
||||||
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
|
||||||
frag_hdr->_nexth = ipr->nexth;
|
|
||||||
frag_hdr->reserved = 0;
|
|
||||||
frag_hdr->_fragment_offset = 0;
|
|
||||||
frag_hdr->_identification = 0;
|
|
||||||
|
|
||||||
/* release the sources allocate for the fragment queue entry */
|
|
||||||
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", ipr_prev != NULL);
|
|
||||||
ipr_prev->next = ipr->next;
|
|
||||||
}
|
|
||||||
memp_free(MEMP_IP6_REASSDATA, ipr);
|
|
||||||
|
|
||||||
/* adjust the number of pbufs currently queued for reassembly. */
|
|
||||||
ip6_reass_pbufcount -= pbuf_clen(p);
|
|
||||||
|
|
||||||
/* Move pbuf back to IPv6 header.
|
|
||||||
This cannot fail since we already checked when receiving this fragment. */
|
|
||||||
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) {
|
|
||||||
LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0);
|
|
||||||
pbuf_free(p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the pbuf chain */
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
/* the datagram is not (yet?) reassembled completely */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
nullreturn:
|
|
||||||
pbuf_free(p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_FRAG
|
|
||||||
|
|
||||||
/** Allocate a new struct pbuf_custom_ref */
|
|
||||||
static struct pbuf_custom_ref*
|
|
||||||
ip6_frag_alloc_pbuf_custom_ref(void)
|
|
||||||
{
|
|
||||||
return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Free a struct pbuf_custom_ref */
|
|
||||||
static void
|
|
||||||
ip6_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
|
|
||||||
ip6_frag_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);
|
|
||||||
}
|
|
||||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
|
||||||
*
|
|
||||||
* Chop the datagram in MTU sized chunks and send them in order
|
|
||||||
* by pointing PBUF_REFs into p
|
|
||||||
*
|
|
||||||
* @param p ipv6 packet to send
|
|
||||||
* @param netif the netif on which to send
|
|
||||||
* @param dest destination ipv6 address to which to send
|
|
||||||
*
|
|
||||||
* @return ERR_OK if sent successfully, err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|
||||||
{
|
|
||||||
struct ip6_hdr *original_ip6hdr;
|
|
||||||
struct ip6_hdr *ip6hdr;
|
|
||||||
struct ip6_frag_hdr * frag_hdr;
|
|
||||||
struct pbuf *rambuf;
|
|
||||||
struct pbuf *newpbuf;
|
|
||||||
static u32_t identification;
|
|
||||||
u16_t nfb;
|
|
||||||
u16_t left, cop;
|
|
||||||
u16_t mtu;
|
|
||||||
u16_t fragment_offset = 0;
|
|
||||||
u16_t last;
|
|
||||||
u16_t poff = IP6_HLEN;
|
|
||||||
u16_t newpbuflen = 0;
|
|
||||||
u16_t left_to_copy;
|
|
||||||
|
|
||||||
identification++;
|
|
||||||
|
|
||||||
original_ip6hdr = (struct ip6_hdr *)p->payload;
|
|
||||||
|
|
||||||
mtu = nd6_get_destination_mtu(dest, netif);
|
|
||||||
|
|
||||||
/* TODO we assume there are no options in the unfragmentable part (IPv6 header). */
|
|
||||||
left = p->tot_len - IP6_HLEN;
|
|
||||||
|
|
||||||
nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;
|
|
||||||
|
|
||||||
while (left) {
|
|
||||||
last = (left <= nfb);
|
|
||||||
|
|
||||||
/* Fill this fragment */
|
|
||||||
cop = last ? left : nfb;
|
|
||||||
|
|
||||||
/* When not using a static buffer, create a chain of pbufs.
|
|
||||||
* The first will be a PBUF_RAM holding the link, IPv6, and Fragment 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, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM);
|
|
||||||
if (rambuf == NULL) {
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("this needs a pbuf in one piece!",
|
|
||||||
(p->len >= (IP6_HLEN + IP6_FRAG_HLEN)));
|
|
||||||
SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
|
|
||||||
ip6hdr = (struct ip6_hdr *)rambuf->payload;
|
|
||||||
frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);
|
|
||||||
|
|
||||||
/* Can just adjust p directly for needed offset. */
|
|
||||||
p->payload = (u8_t *)p->payload + poff;
|
|
||||||
p->len -= poff;
|
|
||||||
p->tot_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 = ip6_frag_alloc_pbuf_custom_ref();
|
|
||||||
if (pcr == NULL) {
|
|
||||||
pbuf_free(rambuf);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
|
||||||
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) {
|
|
||||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
|
||||||
pbuf_free(rambuf);
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
pbuf_ref(p);
|
|
||||||
pcr->original = p;
|
|
||||||
pcr->pc.custom_free_function = ip6_frag_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;
|
|
||||||
|
|
||||||
/* Set headers */
|
|
||||||
frag_hdr->_nexth = original_ip6hdr->_nexth;
|
|
||||||
frag_hdr->reserved = 0;
|
|
||||||
frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
|
|
||||||
frag_hdr->_identification = htonl(identification);
|
|
||||||
|
|
||||||
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
|
||||||
IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
|
|
||||||
|
|
||||||
/* No need for separate header pbuf - we allowed room for it in rambuf
|
|
||||||
* when allocated.
|
|
||||||
*/
|
|
||||||
IP6_FRAG_STATS_INC(ip6_frag.xmit);
|
|
||||||
netif->output_ip6(netif, rambuf, dest);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
left -= cop;
|
|
||||||
fragment_offset += cop;
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */
|
|
|
@ -1,588 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
|
||||||
* No support for MLDv2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Based on igmp.c implementation of igmp v2 protocol */
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/icmp6.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/inet_chksum.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MLD constants
|
|
||||||
*/
|
|
||||||
#define MLD6_HL 1
|
|
||||||
#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500)
|
|
||||||
|
|
||||||
#define MLD6_GROUP_NON_MEMBER 0
|
|
||||||
#define MLD6_GROUP_DELAYING_MEMBER 1
|
|
||||||
#define MLD6_GROUP_IDLE_MEMBER 2
|
|
||||||
|
|
||||||
|
|
||||||
/* The list of joined groups. */
|
|
||||||
static struct mld_group* mld_group_list;
|
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations. */
|
|
||||||
static struct mld_group * mld6_new_group(struct netif *ifp, const ip6_addr_t *addr);
|
|
||||||
static err_t mld6_free_group(struct mld_group *group);
|
|
||||||
static void mld6_delayed_report(struct mld_group *group, u16_t maxresp);
|
|
||||||
static void mld6_send(struct mld_group *group, u8_t type);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop MLD processing on interface
|
|
||||||
*
|
|
||||||
* @param netif network interface on which stop MLD processing
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
mld6_stop(struct netif *netif)
|
|
||||||
{
|
|
||||||
struct mld_group *group = mld_group_list;
|
|
||||||
struct mld_group *prev = NULL;
|
|
||||||
struct mld_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 == mld_group_list) {
|
|
||||||
mld_group_list = next;
|
|
||||||
}
|
|
||||||
/* is there a "previous" group defined? */
|
|
||||||
if (prev != NULL) {
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
/* disable the group at the MAC level */
|
|
||||||
if (netif->mld_mac_filter != NULL) {
|
|
||||||
netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER);
|
|
||||||
}
|
|
||||||
/* free group */
|
|
||||||
memp_free(MEMP_MLD6_GROUP, group);
|
|
||||||
} else {
|
|
||||||
/* change the "previous" */
|
|
||||||
prev = group;
|
|
||||||
}
|
|
||||||
/* move to "next" */
|
|
||||||
group = next;
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report MLD memberships for this interface
|
|
||||||
*
|
|
||||||
* @param netif network interface on which report MLD memberships
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mld6_report_groups(struct netif *netif)
|
|
||||||
{
|
|
||||||
struct mld_group *group = mld_group_list;
|
|
||||||
|
|
||||||
while (group != NULL) {
|
|
||||||
if (group->netif == netif) {
|
|
||||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
|
||||||
}
|
|
||||||
group = group->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for a group that is joined on a netif
|
|
||||||
*
|
|
||||||
* @param ifp the network interface for which to look
|
|
||||||
* @param addr the group ipv6 address to search for
|
|
||||||
* @return a struct mld_group* if the group has been found,
|
|
||||||
* NULL if the group wasn't found.
|
|
||||||
*/
|
|
||||||
struct mld_group *
|
|
||||||
mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr)
|
|
||||||
{
|
|
||||||
struct mld_group *group = mld_group_list;
|
|
||||||
|
|
||||||
while (group != NULL) {
|
|
||||||
if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
group = group->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a new group
|
|
||||||
*
|
|
||||||
* @param ifp the network interface for which to create
|
|
||||||
* @param addr the new group ipv6
|
|
||||||
* @return a struct mld_group*,
|
|
||||||
* NULL on memory error.
|
|
||||||
*/
|
|
||||||
static struct mld_group *
|
|
||||||
mld6_new_group(struct netif *ifp, const ip6_addr_t *addr)
|
|
||||||
{
|
|
||||||
struct mld_group *group;
|
|
||||||
|
|
||||||
group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP);
|
|
||||||
if (group != NULL) {
|
|
||||||
group->netif = ifp;
|
|
||||||
ip6_addr_set(&(group->group_address), addr);
|
|
||||||
group->timer = 0; /* Not running */
|
|
||||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
|
||||||
group->last_reporter_flag = 0;
|
|
||||||
group->use = 0;
|
|
||||||
group->next = mld_group_list;
|
|
||||||
|
|
||||||
mld_group_list = group;
|
|
||||||
}
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a group in the mld_group_list and free
|
|
||||||
*
|
|
||||||
* @param group the group to remove
|
|
||||||
* @return ERR_OK if group was removed from the list, an err_t otherwise
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
mld6_free_group(struct mld_group *group)
|
|
||||||
{
|
|
||||||
err_t err = ERR_OK;
|
|
||||||
|
|
||||||
/* Is it the first group? */
|
|
||||||
if (mld_group_list == group) {
|
|
||||||
mld_group_list = group->next;
|
|
||||||
} else {
|
|
||||||
/* look for group further down the list */
|
|
||||||
struct mld_group *tmpGroup;
|
|
||||||
for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
|
||||||
if (tmpGroup->next == group) {
|
|
||||||
tmpGroup->next = group->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Group not find group */
|
|
||||||
if (tmpGroup == NULL) {
|
|
||||||
err = ERR_ARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* free group */
|
|
||||||
memp_free(MEMP_MLD6_GROUP, group);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an input MLD message. Called by icmp6_input.
|
|
||||||
*
|
|
||||||
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
|
||||||
* @param inp the netif on which this packet was received
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mld6_input(struct pbuf *p, struct netif *inp)
|
|
||||||
{
|
|
||||||
struct mld_header * mld_hdr;
|
|
||||||
struct mld_group* group;
|
|
||||||
|
|
||||||
MLD6_STATS_INC(mld6.recv);
|
|
||||||
|
|
||||||
/* Check that mld header fits in packet. */
|
|
||||||
if (p->len < sizeof(struct mld_header)) {
|
|
||||||
/* TODO debug message */
|
|
||||||
pbuf_free(p);
|
|
||||||
MLD6_STATS_INC(mld6.lenerr);
|
|
||||||
MLD6_STATS_INC(mld6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mld_hdr = (struct mld_header *)p->payload;
|
|
||||||
|
|
||||||
switch (mld_hdr->type) {
|
|
||||||
case ICMP6_TYPE_MLQ: /* Multicast listener query. */
|
|
||||||
/* Is it a general query? */
|
|
||||||
if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
|
|
||||||
ip6_addr_isany(&(mld_hdr->multicast_address))) {
|
|
||||||
MLD6_STATS_INC(mld6.rx_general);
|
|
||||||
/* Report all groups, except all nodes group, and if-local groups. */
|
|
||||||
group = mld_group_list;
|
|
||||||
while (group != NULL) {
|
|
||||||
if ((group->netif == inp) &&
|
|
||||||
(!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
|
|
||||||
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
|
|
||||||
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
|
||||||
}
|
|
||||||
group = group->next;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Have we joined this group?
|
|
||||||
* We use IP6 destination address to have a memory aligned copy.
|
|
||||||
* mld_hdr->multicast_address should be the same. */
|
|
||||||
MLD6_STATS_INC(mld6.rx_group);
|
|
||||||
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
|
||||||
if (group != NULL) {
|
|
||||||
/* Schedule a report. */
|
|
||||||
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break; /* ICMP6_TYPE_MLQ */
|
|
||||||
case ICMP6_TYPE_MLR: /* Multicast listener report. */
|
|
||||||
/* Have we joined this group?
|
|
||||||
* We use IP6 destination address to have a memory aligned copy.
|
|
||||||
* mld_hdr->multicast_address should be the same. */
|
|
||||||
MLD6_STATS_INC(mld6.rx_report);
|
|
||||||
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
|
||||||
if (group != NULL) {
|
|
||||||
/* If we are waiting to report, cancel it. */
|
|
||||||
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
|
||||||
group->timer = 0; /* stopped */
|
|
||||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
|
||||||
group->last_reporter_flag = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break; /* ICMP6_TYPE_MLR */
|
|
||||||
case ICMP6_TYPE_MLD: /* Multicast listener done. */
|
|
||||||
/* Do nothing, router will query us. */
|
|
||||||
break; /* ICMP6_TYPE_MLD */
|
|
||||||
default:
|
|
||||||
MLD6_STATS_INC(mld6.proterr);
|
|
||||||
MLD6_STATS_INC(mld6.drop);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join a group on a network interface.
|
|
||||||
*
|
|
||||||
* @param srcaddr ipv6 address of the network interface which should
|
|
||||||
* join a new group. If IP6_ADDR_ANY, join on all netifs
|
|
||||||
* @param groupaddr the ipv6 address of the group to join
|
|
||||||
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
err_t err = ERR_VAL; /* no matching interface */
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* loop through netif's */
|
|
||||||
netif = netif_list;
|
|
||||||
while (netif != NULL) {
|
|
||||||
/* Should we join this interface ? */
|
|
||||||
if (ip6_addr_isany(srcaddr) ||
|
|
||||||
netif_get_ip6_addr_match(netif, srcaddr) >= 0) {
|
|
||||||
err = mld6_joingroup_netif(netif, groupaddr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* proceed to next network interface */
|
|
||||||
netif = netif->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join a group on a network interface.
|
|
||||||
*
|
|
||||||
* @param netif the network interface which should join a new group.
|
|
||||||
* @param groupaddr the ipv6 address of the group to join
|
|
||||||
* @return ERR_OK if group was joined on the netif, an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
struct mld_group *group;
|
|
||||||
|
|
||||||
/* find group or create a new one if not found */
|
|
||||||
group = mld6_lookfor_group(netif, groupaddr);
|
|
||||||
|
|
||||||
if (group == NULL) {
|
|
||||||
/* Joining a new group. Create a new group entry. */
|
|
||||||
group = mld6_new_group(netif, groupaddr);
|
|
||||||
if (group == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Activate this address on the MAC layer. */
|
|
||||||
if (netif->mld_mac_filter != NULL) {
|
|
||||||
netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Report our membership. */
|
|
||||||
MLD6_STATS_INC(mld6.tx_report);
|
|
||||||
mld6_send(group, ICMP6_TYPE_MLR);
|
|
||||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment group use */
|
|
||||||
group->use++;
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leave a group on a network interface.
|
|
||||||
*
|
|
||||||
* @param srcaddr ipv6 address of the network interface which should
|
|
||||||
* leave the group. If IP6_ISANY, leave on all netifs
|
|
||||||
* @param groupaddr the ipv6 address of the group to leave
|
|
||||||
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
err_t err = ERR_VAL; /* no matching interface */
|
|
||||||
struct netif *netif;
|
|
||||||
|
|
||||||
/* loop through netif's */
|
|
||||||
netif = netif_list;
|
|
||||||
while (netif != NULL) {
|
|
||||||
/* Should we leave this interface ? */
|
|
||||||
if (ip6_addr_isany(srcaddr) ||
|
|
||||||
netif_get_ip6_addr_match(netif, srcaddr) >= 0) {
|
|
||||||
err_t res = mld6_leavegroup_netif(netif, groupaddr);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
/* Store this result if we have not yet gotten a success */
|
|
||||||
err = res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* proceed to next network interface */
|
|
||||||
netif = netif->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leave a group on a network interface.
|
|
||||||
*
|
|
||||||
* @param netif the network interface which should leave the group.
|
|
||||||
* @param groupaddr the ipv6 address of the group to leave
|
|
||||||
* @return ERR_OK if group was left on the netif, an err_t otherwise
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
|
|
||||||
{
|
|
||||||
struct mld_group *group;
|
|
||||||
|
|
||||||
/* find group */
|
|
||||||
group = mld6_lookfor_group(netif, groupaddr);
|
|
||||||
|
|
||||||
if (group != NULL) {
|
|
||||||
/* Leave 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) {
|
|
||||||
MLD6_STATS_INC(mld6.tx_leave);
|
|
||||||
mld6_send(group, ICMP6_TYPE_MLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable the group at the MAC level */
|
|
||||||
if (netif->mld_mac_filter != NULL) {
|
|
||||||
netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the group */
|
|
||||||
mld6_free_group(group);
|
|
||||||
} else {
|
|
||||||
/* Decrement group use */
|
|
||||||
group->use--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Left group */
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Group not found */
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Periodic timer for mld processing. Must be called every
|
|
||||||
* MLD6_TMR_INTERVAL milliseconds (100).
|
|
||||||
*
|
|
||||||
* When a delaying member expires, a membership report is sent.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mld6_tmr(void)
|
|
||||||
{
|
|
||||||
struct mld_group *group = mld_group_list;
|
|
||||||
|
|
||||||
while (group != NULL) {
|
|
||||||
if (group->timer > 0) {
|
|
||||||
group->timer--;
|
|
||||||
if (group->timer == 0) {
|
|
||||||
/* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
|
|
||||||
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
|
||||||
MLD6_STATS_INC(mld6.tx_report);
|
|
||||||
mld6_send(group, ICMP6_TYPE_MLR);
|
|
||||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
group = group->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule a delayed membership report for a group
|
|
||||||
*
|
|
||||||
* @param group the mld_group for which "delaying" membership report
|
|
||||||
* should be sent
|
|
||||||
* @param maxresp the max resp delay provided in the query
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
mld6_delayed_report(struct mld_group *group, u16_t maxresp)
|
|
||||||
{
|
|
||||||
/* Convert maxresp from milliseconds to tmr ticks */
|
|
||||||
maxresp = maxresp / MLD6_TMR_INTERVAL;
|
|
||||||
if (maxresp == 0) {
|
|
||||||
maxresp = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LWIP_RAND
|
|
||||||
/* Randomize maxresp. (if LWIP_RAND is supported) */
|
|
||||||
maxresp = LWIP_RAND() % maxresp;
|
|
||||||
if (maxresp == 0) {
|
|
||||||
maxresp = 1;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_RAND */
|
|
||||||
|
|
||||||
/* Apply timer value if no report has been scheduled already. */
|
|
||||||
if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) ||
|
|
||||||
((group->group_state == MLD6_GROUP_DELAYING_MEMBER) &&
|
|
||||||
((group->timer == 0) || (maxresp < group->timer)))) {
|
|
||||||
group->timer = maxresp;
|
|
||||||
group->group_state = MLD6_GROUP_DELAYING_MEMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a MLD message (report or done).
|
|
||||||
*
|
|
||||||
* An IPv6 hop-by-hop options header with a router alert option
|
|
||||||
* is prepended.
|
|
||||||
*
|
|
||||||
* @param group the group to report or quit
|
|
||||||
* @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
mld6_send(struct mld_group *group, u8_t type)
|
|
||||||
{
|
|
||||||
struct mld_header * mld_hdr;
|
|
||||||
struct pbuf * p;
|
|
||||||
const ip6_addr_t * src_addr;
|
|
||||||
|
|
||||||
/* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */
|
|
||||||
p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM);
|
|
||||||
if (p == NULL) {
|
|
||||||
MLD6_STATS_INC(mld6.memerr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move to make room for Hop-by-hop options header. */
|
|
||||||
if (pbuf_header(p, -IP6_HBH_HLEN)) {
|
|
||||||
pbuf_free(p);
|
|
||||||
MLD6_STATS_INC(mld6.lenerr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select our source address. */
|
|
||||||
if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
|
|
||||||
/* This is a special case, when we are performing duplicate address detection.
|
|
||||||
* We must join the multicast group, but we don't have a valid address yet. */
|
|
||||||
src_addr = IP6_ADDR_ANY6;
|
|
||||||
} else {
|
|
||||||
/* Use link-local address as source address. */
|
|
||||||
src_addr = netif_ip6_addr(group->netif, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MLD message header pointer. */
|
|
||||||
mld_hdr = (struct mld_header *)p->payload;
|
|
||||||
|
|
||||||
/* Set fields. */
|
|
||||||
mld_hdr->type = type;
|
|
||||||
mld_hdr->code = 0;
|
|
||||||
mld_hdr->chksum = 0;
|
|
||||||
mld_hdr->max_resp_delay = 0;
|
|
||||||
mld_hdr->reserved = 0;
|
|
||||||
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
|
|
||||||
|
|
||||||
#if CHECKSUM_GEN_ICMP6
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
|
||||||
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
|
|
||||||
src_addr, &(group->group_address));
|
|
||||||
}
|
|
||||||
#endif /* CHECKSUM_GEN_ICMP6 */
|
|
||||||
|
|
||||||
/* Add hop-by-hop headers options: router alert with MLD value. */
|
|
||||||
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
|
|
||||||
|
|
||||||
/* Send the packet out. */
|
|
||||||
MLD6_STATS_INC(mld6.xmit);
|
|
||||||
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
|
|
||||||
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif);
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,682 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Dynamic memory manager
|
|
||||||
*
|
|
||||||
* This is a lightweight replacement for the standard C library malloc().
|
|
||||||
*
|
|
||||||
* If you want to use the standard C library malloc() instead, define
|
|
||||||
* MEM_LIBC_MALLOC to 1 in your lwipopts.h
|
|
||||||
*
|
|
||||||
* To let mem_malloc() use pools (prevents fragmentation and is much faster than
|
|
||||||
* a heap but might waste some memory), define MEM_USE_POOLS to 1, define
|
|
||||||
* MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list
|
|
||||||
* of pools like this (more pools can be added between _START and _END):
|
|
||||||
*
|
|
||||||
* Define three pools with sizes 256, 512, and 1512 bytes
|
|
||||||
* LWIP_MALLOC_MEMPOOL_START
|
|
||||||
* LWIP_MALLOC_MEMPOOL(20, 256)
|
|
||||||
* LWIP_MALLOC_MEMPOOL(10, 512)
|
|
||||||
* LWIP_MALLOC_MEMPOOL(5, 1512)
|
|
||||||
* LWIP_MALLOC_MEMPOOL_END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
* Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if MEM_USE_POOLS
|
|
||||||
|
|
||||||
#if MEMP_MEM_MALLOC
|
|
||||||
#error MEM_USE_POOLS and MEMP_MEM_MALLOC cannot be used together
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* lwIP head implemented with different sized pools */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate memory: determine the smallest pool that is big enough
|
|
||||||
* to contain an element of 'size' and get an element from that pool.
|
|
||||||
*
|
|
||||||
* @param size the size in bytes of the memory needed
|
|
||||||
* @return a pointer to the allocated memory or NULL if the pool is empty
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
mem_malloc(mem_size_t size)
|
|
||||||
{
|
|
||||||
void *ret;
|
|
||||||
struct memp_malloc_helper *element;
|
|
||||||
memp_t poolnr;
|
|
||||||
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
|
||||||
|
|
||||||
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
|
|
||||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
|
||||||
again:
|
|
||||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
|
||||||
/* is this pool big enough to hold an element of the required size
|
|
||||||
plus a struct memp_malloc_helper that saves the pool this element came from? */
|
|
||||||
if (required_size <= memp_pools[poolnr]->size) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (poolnr > MEMP_POOL_LAST) {
|
|
||||||
LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
element = (struct memp_malloc_helper*)memp_malloc(poolnr);
|
|
||||||
if (element == NULL) {
|
|
||||||
/* No need to DEBUGF or ASSERT: This error is already
|
|
||||||
taken care of in memp.c */
|
|
||||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
|
||||||
/** Try a bigger pool if this one is empty! */
|
|
||||||
if (poolnr < MEMP_POOL_LAST) {
|
|
||||||
poolnr++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the pool number this element came from */
|
|
||||||
element->poolnr = poolnr;
|
|
||||||
/* and return a pointer to the memory directly after the struct memp_malloc_helper */
|
|
||||||
ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
/* initialize unused memory */
|
|
||||||
element->size = size;
|
|
||||||
memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free memory previously allocated by mem_malloc. Loads the pool number
|
|
||||||
* and calls memp_free with that pool number to put the element back into
|
|
||||||
* its pool
|
|
||||||
*
|
|
||||||
* @param rmem the memory element to free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mem_free(void *rmem)
|
|
||||||
{
|
|
||||||
struct memp_malloc_helper *hmem;
|
|
||||||
|
|
||||||
LWIP_ASSERT("rmem != NULL", (rmem != NULL));
|
|
||||||
LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
|
|
||||||
|
|
||||||
/* get the original struct memp_malloc_helper */
|
|
||||||
hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)));
|
|
||||||
|
|
||||||
LWIP_ASSERT("hmem != NULL", (hmem != NULL));
|
|
||||||
LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
|
|
||||||
LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
{
|
|
||||||
u16_t i;
|
|
||||||
LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size",
|
|
||||||
hmem->size <= memp_pools[hmem->poolnr]->size);
|
|
||||||
/* check that unused memory remained untouched */
|
|
||||||
for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) {
|
|
||||||
u8_t data = *((u8_t*)rmem + i);
|
|
||||||
LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
/* and put it in the pool we saved earlier */
|
|
||||||
memp_free(hmem->poolnr, hmem);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* MEM_USE_POOLS */
|
|
||||||
/* lwIP replacement for your libc malloc() */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The heap is made up as a list of structs of this type.
|
|
||||||
* This does not have to be aligned since for getting its size,
|
|
||||||
* we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns.
|
|
||||||
*/
|
|
||||||
struct mem {
|
|
||||||
/** index (-> ram[next]) of the next struct */
|
|
||||||
mem_size_t next;
|
|
||||||
/** index (-> ram[prev]) of the previous struct */
|
|
||||||
mem_size_t prev;
|
|
||||||
/** 1: this area is used; 0: this area is unused */
|
|
||||||
u8_t used;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** All allocated blocks will be MIN_SIZE bytes big, at least!
|
|
||||||
* MIN_SIZE can be overridden to suit your needs. Smaller values save space,
|
|
||||||
* larger values could prevent too small blocks to fragment the RAM too much. */
|
|
||||||
#ifndef MIN_SIZE
|
|
||||||
#define MIN_SIZE 12
|
|
||||||
#endif /* MIN_SIZE */
|
|
||||||
/* some alignment macros: we define them here for better source code layout */
|
|
||||||
#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
|
|
||||||
#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
|
|
||||||
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
|
|
||||||
|
|
||||||
/** If you want to relocate the heap to external memory, simply define
|
|
||||||
* LWIP_RAM_HEAP_POINTER as a void-pointer to that location.
|
|
||||||
* If so, make sure the memory at that location is big enough (see below on
|
|
||||||
* how that space is calculated). */
|
|
||||||
#ifndef LWIP_RAM_HEAP_POINTER
|
|
||||||
/** the heap. we need one struct mem at the end and some room for alignment */
|
|
||||||
u8_t ram_heap[MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
|
|
||||||
#define LWIP_RAM_HEAP_POINTER ram_heap
|
|
||||||
#endif /* LWIP_RAM_HEAP_POINTER */
|
|
||||||
|
|
||||||
/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
|
|
||||||
static u8_t *ram;
|
|
||||||
/** the last entry, always unused! */
|
|
||||||
static struct mem *ram_end;
|
|
||||||
/** pointer to the lowest free block, this is used for faster search */
|
|
||||||
static struct mem *lfree;
|
|
||||||
|
|
||||||
/** concurrent access protection */
|
|
||||||
#if !NO_SYS
|
|
||||||
static sys_mutex_t mem_mutex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
|
|
||||||
static volatile u8_t mem_free_count;
|
|
||||||
|
|
||||||
/* Allow mem_free from other (e.g. interrupt) context */
|
|
||||||
#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
|
|
||||||
#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
|
|
||||||
#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
|
|
||||||
#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
|
|
||||||
#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
|
|
||||||
#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
|
|
||||||
|
|
||||||
#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
|
|
||||||
/* Protect the heap only by using a semaphore */
|
|
||||||
#define LWIP_MEM_FREE_DECL_PROTECT()
|
|
||||||
#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
|
|
||||||
#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
|
|
||||||
/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
|
|
||||||
#define LWIP_MEM_ALLOC_DECL_PROTECT()
|
|
||||||
#define LWIP_MEM_ALLOC_PROTECT()
|
|
||||||
#define LWIP_MEM_ALLOC_UNPROTECT()
|
|
||||||
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "Plug holes" by combining adjacent empty struct mems.
|
|
||||||
* After this function is through, there should not exist
|
|
||||||
* one empty struct mem pointing to another empty struct mem.
|
|
||||||
*
|
|
||||||
* @param mem this points to a struct mem which just has been freed
|
|
||||||
* @internal this function is only called by mem_free() and mem_trim()
|
|
||||||
*
|
|
||||||
* This assumes access to the heap is protected by the calling function
|
|
||||||
* already.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
plug_holes(struct mem *mem)
|
|
||||||
{
|
|
||||||
struct mem *nmem;
|
|
||||||
struct mem *pmem;
|
|
||||||
|
|
||||||
LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
|
|
||||||
LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
|
|
||||||
LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
|
|
||||||
|
|
||||||
/* plug hole forward */
|
|
||||||
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
|
|
||||||
|
|
||||||
nmem = (struct mem *)(void *)&ram[mem->next];
|
|
||||||
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
|
|
||||||
/* if mem->next is unused and not end of ram, combine mem and mem->next */
|
|
||||||
if (lfree == nmem) {
|
|
||||||
lfree = mem;
|
|
||||||
}
|
|
||||||
mem->next = nmem->next;
|
|
||||||
((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* plug hole backward */
|
|
||||||
pmem = (struct mem *)(void *)&ram[mem->prev];
|
|
||||||
if (pmem != mem && pmem->used == 0) {
|
|
||||||
/* if mem->prev is unused, combine mem and mem->prev */
|
|
||||||
if (lfree == mem) {
|
|
||||||
lfree = pmem;
|
|
||||||
}
|
|
||||||
pmem->next = mem->next;
|
|
||||||
((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero the heap and initialize start, end and lowest-free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mem_init(void)
|
|
||||||
{
|
|
||||||
struct mem *mem;
|
|
||||||
|
|
||||||
LWIP_ASSERT("Sanity check alignment",
|
|
||||||
(SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
|
|
||||||
|
|
||||||
/* align the heap */
|
|
||||||
ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
|
|
||||||
/* initialize the start of the heap */
|
|
||||||
mem = (struct mem *)(void *)ram;
|
|
||||||
mem->next = MEM_SIZE_ALIGNED;
|
|
||||||
mem->prev = 0;
|
|
||||||
mem->used = 0;
|
|
||||||
/* initialize the end of the heap */
|
|
||||||
ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
|
|
||||||
ram_end->used = 1;
|
|
||||||
ram_end->next = MEM_SIZE_ALIGNED;
|
|
||||||
ram_end->prev = MEM_SIZE_ALIGNED;
|
|
||||||
|
|
||||||
/* initialize the lowest-free pointer to the start of the heap */
|
|
||||||
lfree = (struct mem *)(void *)ram;
|
|
||||||
|
|
||||||
MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
|
|
||||||
|
|
||||||
if (sys_mutex_new(&mem_mutex) != ERR_OK) {
|
|
||||||
LWIP_ASSERT("failed to create mem_mutex", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put a struct mem back on the heap
|
|
||||||
*
|
|
||||||
* @param rmem is the data portion of a struct mem as returned by a previous
|
|
||||||
* call to mem_malloc()
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mem_free(void *rmem)
|
|
||||||
{
|
|
||||||
struct mem *mem;
|
|
||||||
LWIP_MEM_FREE_DECL_PROTECT();
|
|
||||||
|
|
||||||
if (rmem == NULL) {
|
|
||||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
|
|
||||||
|
|
||||||
LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
|
||||||
(u8_t *)rmem < (u8_t *)ram_end);
|
|
||||||
|
|
||||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
|
||||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
|
|
||||||
/* protect mem stats from concurrent access */
|
|
||||||
SYS_ARCH_PROTECT(lev);
|
|
||||||
MEM_STATS_INC(illegal);
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* protect the heap from concurrent access */
|
|
||||||
LWIP_MEM_FREE_PROTECT();
|
|
||||||
/* Get the corresponding struct mem ... */
|
|
||||||
mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
|
||||||
/* ... which has to be in a used state ... */
|
|
||||||
LWIP_ASSERT("mem_free: mem->used", mem->used);
|
|
||||||
/* ... and is now unused. */
|
|
||||||
mem->used = 0;
|
|
||||||
|
|
||||||
if (mem < lfree) {
|
|
||||||
/* the newly freed struct is now the lowest */
|
|
||||||
lfree = mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
|
|
||||||
|
|
||||||
/* finally, see if prev or next are free also */
|
|
||||||
plug_holes(mem);
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
mem_free_count = 1;
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
LWIP_MEM_FREE_UNPROTECT();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shrink memory returned by mem_malloc().
|
|
||||||
*
|
|
||||||
* @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
|
|
||||||
* @param newsize required size after shrinking (needs to be smaller than or
|
|
||||||
* equal to the previous size)
|
|
||||||
* @return for compatibility reasons: is always == rmem, at the moment
|
|
||||||
* or NULL if newsize is > old size, in which case rmem is NOT touched
|
|
||||||
* or freed!
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
mem_trim(void *rmem, mem_size_t newsize)
|
|
||||||
{
|
|
||||||
mem_size_t size;
|
|
||||||
mem_size_t ptr, ptr2;
|
|
||||||
struct mem *mem, *mem2;
|
|
||||||
/* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
|
|
||||||
LWIP_MEM_FREE_DECL_PROTECT();
|
|
||||||
|
|
||||||
/* Expand the size of the allocated memory region so that we can
|
|
||||||
adjust for alignment. */
|
|
||||||
newsize = LWIP_MEM_ALIGN_SIZE(newsize);
|
|
||||||
|
|
||||||
if (newsize < MIN_SIZE_ALIGNED) {
|
|
||||||
/* every data block must be at least MIN_SIZE_ALIGNED long */
|
|
||||||
newsize = MIN_SIZE_ALIGNED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newsize > MEM_SIZE_ALIGNED) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
|
||||||
(u8_t *)rmem < (u8_t *)ram_end);
|
|
||||||
|
|
||||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
|
||||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
|
|
||||||
/* protect mem stats from concurrent access */
|
|
||||||
SYS_ARCH_PROTECT(lev);
|
|
||||||
MEM_STATS_INC(illegal);
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
return rmem;
|
|
||||||
}
|
|
||||||
/* Get the corresponding struct mem ... */
|
|
||||||
mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
|
||||||
/* ... and its offset pointer */
|
|
||||||
ptr = (mem_size_t)((u8_t *)mem - ram);
|
|
||||||
|
|
||||||
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
|
|
||||||
LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
|
|
||||||
if (newsize > size) {
|
|
||||||
/* not supported */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (newsize == size) {
|
|
||||||
/* No change in size, simply return */
|
|
||||||
return rmem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* protect the heap from concurrent access */
|
|
||||||
LWIP_MEM_FREE_PROTECT();
|
|
||||||
|
|
||||||
mem2 = (struct mem *)(void *)&ram[mem->next];
|
|
||||||
if (mem2->used == 0) {
|
|
||||||
/* The next struct is unused, we can simply move it at little */
|
|
||||||
mem_size_t next;
|
|
||||||
/* remember the old next pointer */
|
|
||||||
next = mem2->next;
|
|
||||||
/* create new struct mem which is moved directly after the shrinked mem */
|
|
||||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
|
||||||
if (lfree == mem2) {
|
|
||||||
lfree = (struct mem *)(void *)&ram[ptr2];
|
|
||||||
}
|
|
||||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
|
||||||
mem2->used = 0;
|
|
||||||
/* restore the next pointer */
|
|
||||||
mem2->next = next;
|
|
||||||
/* link it back to mem */
|
|
||||||
mem2->prev = ptr;
|
|
||||||
/* link mem to it */
|
|
||||||
mem->next = ptr2;
|
|
||||||
/* last thing to restore linked list: as we have moved mem2,
|
|
||||||
* let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
|
|
||||||
* the end of the heap */
|
|
||||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
|
||||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
|
||||||
}
|
|
||||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
|
||||||
/* no need to plug holes, we've already done that */
|
|
||||||
} else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
|
|
||||||
/* Next struct is used but there's room for another struct mem with
|
|
||||||
* at least MIN_SIZE_ALIGNED of data.
|
|
||||||
* Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
|
|
||||||
* ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
|
|
||||||
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
|
|
||||||
* region that couldn't hold data, but when mem->next gets freed,
|
|
||||||
* the 2 regions would be combined, resulting in more free memory */
|
|
||||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
|
||||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
|
||||||
if (mem2 < lfree) {
|
|
||||||
lfree = mem2;
|
|
||||||
}
|
|
||||||
mem2->used = 0;
|
|
||||||
mem2->next = mem->next;
|
|
||||||
mem2->prev = ptr;
|
|
||||||
mem->next = ptr2;
|
|
||||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
|
||||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
|
||||||
}
|
|
||||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
|
||||||
/* the original mem->next is used, so no need to plug holes! */
|
|
||||||
}
|
|
||||||
/* else {
|
|
||||||
next struct mem is used but size between mem and mem2 is not big enough
|
|
||||||
to create another struct mem
|
|
||||||
-> don't do anyhting.
|
|
||||||
-> the remaining space stays unused since it is too small
|
|
||||||
} */
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
mem_free_count = 1;
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
LWIP_MEM_FREE_UNPROTECT();
|
|
||||||
return rmem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adam's mem_malloc() plus solution for bug #17922
|
|
||||||
* Allocate a block of memory with a minimum of 'size' bytes.
|
|
||||||
*
|
|
||||||
* @param size is the minimum size of the requested block in bytes.
|
|
||||||
* @return pointer to allocated memory or NULL if no free memory was found.
|
|
||||||
*
|
|
||||||
* Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT).
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
mem_malloc(mem_size_t size)
|
|
||||||
{
|
|
||||||
mem_size_t ptr, ptr2;
|
|
||||||
struct mem *mem, *mem2;
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
u8_t local_mem_free_count = 0;
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
LWIP_MEM_ALLOC_DECL_PROTECT();
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand the size of the allocated memory region so that we can
|
|
||||||
adjust for alignment. */
|
|
||||||
size = LWIP_MEM_ALIGN_SIZE(size);
|
|
||||||
|
|
||||||
if (size < MIN_SIZE_ALIGNED) {
|
|
||||||
/* every data block must be at least MIN_SIZE_ALIGNED long */
|
|
||||||
size = MIN_SIZE_ALIGNED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > MEM_SIZE_ALIGNED) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* protect the heap from concurrent access */
|
|
||||||
sys_mutex_lock(&mem_mutex);
|
|
||||||
LWIP_MEM_ALLOC_PROTECT();
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
/* run as long as a mem_free disturbed mem_malloc or mem_trim */
|
|
||||||
do {
|
|
||||||
local_mem_free_count = 0;
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
|
|
||||||
/* Scan through the heap searching for a free block that is big enough,
|
|
||||||
* beginning with the lowest free block.
|
|
||||||
*/
|
|
||||||
for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
|
|
||||||
ptr = ((struct mem *)(void *)&ram[ptr])->next) {
|
|
||||||
mem = (struct mem *)(void *)&ram[ptr];
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
mem_free_count = 0;
|
|
||||||
LWIP_MEM_ALLOC_UNPROTECT();
|
|
||||||
/* allow mem_free or mem_trim to run */
|
|
||||||
LWIP_MEM_ALLOC_PROTECT();
|
|
||||||
if (mem_free_count != 0) {
|
|
||||||
/* If mem_free or mem_trim have run, we have to restart since they
|
|
||||||
could have altered our current struct mem. */
|
|
||||||
local_mem_free_count = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
|
|
||||||
if ((!mem->used) &&
|
|
||||||
(mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
|
|
||||||
/* mem is not used and at least perfect fit is possible:
|
|
||||||
* mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
|
|
||||||
|
|
||||||
if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
|
|
||||||
/* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
|
|
||||||
* at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
|
|
||||||
* -> split large block, create empty remainder,
|
|
||||||
* remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
|
|
||||||
* mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
|
|
||||||
* struct mem would fit in but no data between mem2 and mem2->next
|
|
||||||
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
|
|
||||||
* region that couldn't hold data, but when mem->next gets freed,
|
|
||||||
* the 2 regions would be combined, resulting in more free memory
|
|
||||||
*/
|
|
||||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
|
||||||
/* create mem2 struct */
|
|
||||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
|
||||||
mem2->used = 0;
|
|
||||||
mem2->next = mem->next;
|
|
||||||
mem2->prev = ptr;
|
|
||||||
/* and insert it between mem and mem->next */
|
|
||||||
mem->next = ptr2;
|
|
||||||
mem->used = 1;
|
|
||||||
|
|
||||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
|
||||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
|
||||||
}
|
|
||||||
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
|
|
||||||
} else {
|
|
||||||
/* (a mem2 struct does no fit into the user data space of mem and mem->next will always
|
|
||||||
* be used at this point: if not we have 2 unused structs in a row, plug_holes should have
|
|
||||||
* take care of this).
|
|
||||||
* -> near fit or exact fit: do not split, no mem2 creation
|
|
||||||
* also can't move mem->next directly behind mem, since mem->next
|
|
||||||
* will always be used at this point!
|
|
||||||
*/
|
|
||||||
mem->used = 1;
|
|
||||||
MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
|
|
||||||
}
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
mem_malloc_adjust_lfree:
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
if (mem == lfree) {
|
|
||||||
struct mem *cur = lfree;
|
|
||||||
/* Find next free block after mem and update lowest free pointer */
|
|
||||||
while (cur->used && cur != ram_end) {
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
mem_free_count = 0;
|
|
||||||
LWIP_MEM_ALLOC_UNPROTECT();
|
|
||||||
/* prevent high interrupt latency... */
|
|
||||||
LWIP_MEM_ALLOC_PROTECT();
|
|
||||||
if (mem_free_count != 0) {
|
|
||||||
/* If mem_free or mem_trim have run, we have to restart since they
|
|
||||||
could have altered our current struct mem or lfree. */
|
|
||||||
goto mem_malloc_adjust_lfree;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
cur = (struct mem *)(void *)&ram[cur->next];
|
|
||||||
}
|
|
||||||
lfree = cur;
|
|
||||||
LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
|
|
||||||
}
|
|
||||||
LWIP_MEM_ALLOC_UNPROTECT();
|
|
||||||
sys_mutex_unlock(&mem_mutex);
|
|
||||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
|
||||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
|
||||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
|
||||||
((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
|
||||||
LWIP_ASSERT("mem_malloc: sanity check alignment",
|
|
||||||
(((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
|
|
||||||
|
|
||||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
|
||||||
/* if we got interrupted by a mem_free, try again */
|
|
||||||
} while (local_mem_free_count != 0);
|
|
||||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
|
||||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
|
||||||
MEM_STATS_INC(err);
|
|
||||||
LWIP_MEM_ALLOC_UNPROTECT();
|
|
||||||
sys_mutex_unlock(&mem_mutex);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MEM_USE_POOLS */
|
|
||||||
/**
|
|
||||||
* Contiguously allocates enough space for count objects that are size bytes
|
|
||||||
* of memory each and returns a pointer to the allocated memory.
|
|
||||||
*
|
|
||||||
* The allocated memory is filled with bytes of value zero.
|
|
||||||
*
|
|
||||||
* @param count number of objects to allocate
|
|
||||||
* @param size size of the objects to allocate
|
|
||||||
* @return pointer to allocated memory / NULL pointer if there is an error
|
|
||||||
*/
|
|
||||||
void *mem_calloc(mem_size_t count, mem_size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
/* allocate 'count' objects of size 'size' */
|
|
||||||
p = mem_malloc(count * size);
|
|
||||||
if (p) {
|
|
||||||
/* zero the memory */
|
|
||||||
memset(p, 0, (size_t)count * (size_t)size);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !MEM_LIBC_MALLOC */
|
|
|
@ -1,432 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Dynamic pool memory manager
|
|
||||||
*
|
|
||||||
* lwIP has dedicated pools for many structures (netconn, protocol control blocks,
|
|
||||||
* packet buffers, ...). All these pools are managed here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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/memp.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/udp.h"
|
|
||||||
#include "lwip/raw.h"
|
|
||||||
#include "lwip/igmp.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/priv/api_msg.h"
|
|
||||||
#include "lwip/sockets.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/timers.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
#include "netif/etharp.h"
|
|
||||||
#include "lwip/ip_frag.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
#include "lwip/netdb.h"
|
|
||||||
#include "netif/ppp/ppp.h"
|
|
||||||
#include "netif/ppp/pppos.h"
|
|
||||||
#include "netif/ppp/pppoe.h"
|
|
||||||
#include "netif/ppp/pppol2tp.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/ip6_frag.h"
|
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/tcp.h"
|
|
||||||
#include "lwip/tcpip.h"
|
|
||||||
#include "lwip/priv/tcp_priv.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
#include "lwip/netifapi.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
|
|
||||||
const struct memp_desc* const memp_pools[MEMP_MAX] = {
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#if MEMP_SANITY_CHECK
|
|
||||||
/**
|
|
||||||
* Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
memp_sanity(const struct memp_desc *desc)
|
|
||||||
{
|
|
||||||
struct memp *t, *h;
|
|
||||||
|
|
||||||
t = *desc->tab;
|
|
||||||
if (t != NULL) {
|
|
||||||
for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
|
|
||||||
h = ((h->next != NULL) ? h->next->next : NULL)) {
|
|
||||||
if (t == h) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif /* MEMP_SANITY_CHECK*/
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a memp element was victim of an overflow
|
|
||||||
* (e.g. the restricted area after it has been altered)
|
|
||||||
*
|
|
||||||
* @param p the memp element to check
|
|
||||||
* @param memp_type the pool p comes from
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc)
|
|
||||||
{
|
|
||||||
u16_t k;
|
|
||||||
u8_t *m;
|
|
||||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
|
||||||
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
|
||||||
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
|
||||||
if (m[k] != 0xcd) {
|
|
||||||
char errstr[128] = "detected memp overflow in pool ";
|
|
||||||
strcat(errstr, desc->desc);
|
|
||||||
LWIP_ASSERT(errstr, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a memp element was victim of an underflow
|
|
||||||
* (e.g. the restricted area before it has been altered)
|
|
||||||
*
|
|
||||||
* @param p the memp element to check
|
|
||||||
* @param memp_type the pool p comes from
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc)
|
|
||||||
{
|
|
||||||
u16_t k;
|
|
||||||
u8_t *m;
|
|
||||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
|
||||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
|
||||||
for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
|
|
||||||
if (m[k] != 0xcd) {
|
|
||||||
char errstr[128] = "detected memp underflow in pool ";
|
|
||||||
strcat(errstr, desc->desc);
|
|
||||||
LWIP_ASSERT(errstr, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do an overflow check for all elements in every pool.
|
|
||||||
*
|
|
||||||
* @see memp_overflow_check_element for a description of the check
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
memp_overflow_check_all(void)
|
|
||||||
{
|
|
||||||
u16_t i, j;
|
|
||||||
struct memp *p;
|
|
||||||
|
|
||||||
for (i = 0; i < MEMP_MAX; ++i) {
|
|
||||||
p = (struct memp *)(size_t)(memp_pools[i]->base);
|
|
||||||
for (j = 0; j < memp_pools[i]->num; ++j) {
|
|
||||||
memp_overflow_check_element_overflow(p, memp_pools[i]);
|
|
||||||
memp_overflow_check_element_underflow(p, memp_pools[i]);
|
|
||||||
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the restricted areas of all memp elements in every pool.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
memp_overflow_init(const struct memp_desc *desc)
|
|
||||||
{
|
|
||||||
u16_t i;
|
|
||||||
struct memp *p;
|
|
||||||
u8_t *m;
|
|
||||||
|
|
||||||
p = (struct memp *)(size_t)(desc->base);
|
|
||||||
for (i = 0; i < desc->num; ++i) {
|
|
||||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
|
||||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
|
||||||
memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
|
|
||||||
#endif
|
|
||||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
|
||||||
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
|
||||||
memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
|
|
||||||
#endif
|
|
||||||
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
memp_init_pool(const struct memp_desc *desc)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct memp *memp;
|
|
||||||
|
|
||||||
*desc->tab = NULL;
|
|
||||||
memp = (struct memp*)LWIP_MEM_ALIGN(desc->base);
|
|
||||||
/* create a linked list of memp elements */
|
|
||||||
for (i = 0; i < desc->num; ++i) {
|
|
||||||
memp->next = *desc->tab;
|
|
||||||
*desc->tab = memp;
|
|
||||||
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
+ MEMP_SANITY_REGION_AFTER_ALIGNED
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
memp_overflow_init(desc);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this module.
|
|
||||||
*
|
|
||||||
* Carves out memp_memory into linked lists for each pool-type.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
memp_init(void)
|
|
||||||
{
|
|
||||||
u16_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < MEMP_MAX; ++i) {
|
|
||||||
MEMP_STATS_AVAIL(used, i, 0);
|
|
||||||
MEMP_STATS_AVAIL(max, i, 0);
|
|
||||||
MEMP_STATS_AVAIL(err, i, 0);
|
|
||||||
MEMP_STATS_AVAIL(avail, i, memp_pools[i]->num);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for every pool: */
|
|
||||||
for (i = 0; i < MEMP_MAX; ++i) {
|
|
||||||
memp_init_pool(memp_pools[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
/* check everything a first time to see if it worked */
|
|
||||||
memp_overflow_check_all();
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
|
||||||
memp_malloc_pool(const struct memp_desc *desc)
|
|
||||||
#else
|
|
||||||
memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct memp *memp;
|
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
|
|
||||||
memp = *desc->tab;
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK == 1
|
|
||||||
memp_overflow_check_element_overflow(memp, desc);
|
|
||||||
memp_overflow_check_element_underflow(memp, desc);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
if (memp != NULL) {
|
|
||||||
*desc->tab = memp->next;
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
memp->next = NULL;
|
|
||||||
memp->file = file;
|
|
||||||
memp->line = line;
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
|
||||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
|
||||||
memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
|
|
||||||
return memp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an element from a specific pool.
|
|
||||||
*
|
|
||||||
* @param type the pool to get an element from
|
|
||||||
*
|
|
||||||
* the debug version has two more parameters:
|
|
||||||
* @param file file name calling this function
|
|
||||||
* @param line number of line where this function is called
|
|
||||||
*
|
|
||||||
* @return a pointer to the allocated memory or a NULL pointer on error
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
|
||||||
memp_malloc(memp_t type)
|
|
||||||
#else
|
|
||||||
memp_malloc_fn(memp_t type, const char* file, const int line)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
void *memp;
|
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
|
||||||
LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
|
|
||||||
|
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
|
||||||
memp_overflow_check_all();
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
|
||||||
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
|
||||||
memp = memp_malloc_pool(memp_pools[type]);
|
|
||||||
#else
|
|
||||||
memp = memp_malloc_pool_fn(memp_pools[type], file, line);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (memp != NULL) {
|
|
||||||
MEMP_STATS_INC(used, type);
|
|
||||||
if(MEMP_STATS_GET(used, type) > MEMP_STATS_GET(max, type)) {
|
|
||||||
MEMP_STATS_AVAIL(max, type, MEMP_STATS_GET(used, type));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_pools[type]->desc));
|
|
||||||
MEMP_STATS_INC(err, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
|
|
||||||
return memp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
do_memp_free_pool(const struct memp_desc* desc, void *mem, struct memp **old_first)
|
|
||||||
#else
|
|
||||||
do_memp_free_pool(const struct memp_desc* desc, void *mem)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct memp *memp;
|
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
|
||||||
LWIP_ASSERT("memp_free: mem properly aligned",
|
|
||||||
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
|
|
||||||
|
|
||||||
memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
|
|
||||||
|
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK == 1
|
|
||||||
memp_overflow_check_element_overflow(memp, desc);
|
|
||||||
memp_overflow_check_element_underflow(memp, desc);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
memp->next = *desc->tab;
|
|
||||||
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
if (old_first)
|
|
||||||
*old_first = *desc->tab;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*desc->tab = memp;
|
|
||||||
|
|
||||||
#if MEMP_SANITY_CHECK
|
|
||||||
LWIP_ASSERT("memp sanity", memp_sanity(desc));
|
|
||||||
#endif /* MEMP_SANITY_CHECK */
|
|
||||||
|
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
memp_free_pool(const struct memp_desc* desc, void *mem)
|
|
||||||
{
|
|
||||||
if ((desc == NULL) || (mem == NULL)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
do_memp_free_pool(desc, mem, NULL);
|
|
||||||
#else
|
|
||||||
do_memp_free_pool(desc, mem);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put an element back into its pool.
|
|
||||||
*
|
|
||||||
* @param type the pool where to put mem
|
|
||||||
* @param mem the memp element to free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
memp_free(memp_t type, void *mem)
|
|
||||||
{
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
struct memp *old_first;
|
|
||||||
#endif
|
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
|
||||||
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
|
|
||||||
|
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
|
||||||
memp_overflow_check_all();
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
|
||||||
|
|
||||||
MEMP_STATS_DEC(used, type);
|
|
||||||
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
do_memp_free_pool(memp_pools[type], mem, &old_first);
|
|
||||||
#else
|
|
||||||
do_memp_free_pool(memp_pools[type], mem);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
|
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
if (old_first == NULL) {
|
|
||||||
LWIP_HOOK_MEMP_AVAILABLE(type);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,479 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Implementation of raw protocol PCBs for low-level handling of
|
|
||||||
* different types of protocols besides (or overriding) those
|
|
||||||
* already available in lwIP.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/raw.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/inet_chksum.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/** The list of RAW PCBs */
|
|
||||||
static struct raw_pcb *raw_pcbs;
|
|
||||||
|
|
||||||
static u8_t
|
|
||||||
raw_input_match(struct raw_pcb *pcb, u8_t broadcast)
|
|
||||||
{
|
|
||||||
LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */
|
|
||||||
|
|
||||||
/* Dual-stack: PCBs listening to any IP type also listen to any IP address */
|
|
||||||
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
|
||||||
#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV
|
|
||||||
if((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only need to check PCB if incoming IP version matches PCB IP version */
|
|
||||||
if(IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) {
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/* Special case: IPv4 broadcast: receive all broadcasts
|
|
||||||
* Note: broadcast variable can only be 1 if it is an IPv4 broadcast */
|
|
||||||
if(broadcast != 0) {
|
|
||||||
#if IP_SOF_BROADCAST_RECV
|
|
||||||
if(ip_get_option(pcb, SOF_BROADCAST))
|
|
||||||
#endif /* IP_SOF_BROADCAST_RECV */
|
|
||||||
{
|
|
||||||
if(ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
/* Handle IPv4 and IPv6: catch all or exact match */
|
|
||||||
if(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if in incoming IP packet is covered by a RAW PCB
|
|
||||||
* and if so, pass it to a user-provided receive callback function.
|
|
||||||
*
|
|
||||||
* Given an incoming IP datagram (as a chain of pbufs) this function
|
|
||||||
* finds a corresponding RAW PCB and calls the corresponding receive
|
|
||||||
* callback function.
|
|
||||||
*
|
|
||||||
* @param p pbuf to be demultiplexed to a RAW PCB.
|
|
||||||
* @param inp network interface on which the datagram was received.
|
|
||||||
* @return - 1 if the packet has been eaten by a RAW PCB receive
|
|
||||||
* callback function. The caller MAY NOT not reference the
|
|
||||||
* packet any longer, and MAY NOT call pbuf_free().
|
|
||||||
* @return - 0 if packet is not eaten (pbuf is still referenced by the
|
|
||||||
* caller).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
u8_t
|
|
||||||
raw_input(struct pbuf *p, struct netif *inp)
|
|
||||||
{
|
|
||||||
struct raw_pcb *pcb, *prev;
|
|
||||||
s16_t proto;
|
|
||||||
u8_t eaten = 0;
|
|
||||||
u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
|
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(inp);
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#if LWIP_IPV4
|
|
||||||
if (IP_HDR_GET_VERSION(p->payload) == 6)
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
{
|
|
||||||
struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
|
|
||||||
proto = IP6H_NEXTH(ip6hdr);
|
|
||||||
}
|
|
||||||
#if LWIP_IPV4
|
|
||||||
else
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
#if LWIP_IPV4
|
|
||||||
{
|
|
||||||
proto = IPH_PROTO((struct ip_hdr *)p->payload);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
prev = NULL;
|
|
||||||
pcb = raw_pcbs;
|
|
||||||
/* loop through all raw pcbs until the packet is eaten by one */
|
|
||||||
/* this allows multiple pcbs to match against the packet by design */
|
|
||||||
while ((eaten == 0) && (pcb != NULL)) {
|
|
||||||
if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) {
|
|
||||||
/* receive callback function available? */
|
|
||||||
if (pcb->recv != NULL) {
|
|
||||||
#ifndef LWIP_NOASSERT
|
|
||||||
void* old_payload = p->payload;
|
|
||||||
#endif
|
|
||||||
/* the receive callback function did not eat the packet? */
|
|
||||||
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
|
||||||
if (eaten != 0) {
|
|
||||||
/* receive function ate the packet */
|
|
||||||
p = NULL;
|
|
||||||
eaten = 1;
|
|
||||||
if (prev != NULL) {
|
|
||||||
/* move the pcb to the front of raw_pcbs so that is
|
|
||||||
found faster next time */
|
|
||||||
prev->next = pcb->next;
|
|
||||||
pcb->next = raw_pcbs;
|
|
||||||
raw_pcbs = pcb;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* sanity-check that the receive callback did not alter the pbuf */
|
|
||||||
LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
|
|
||||||
p->payload == old_payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* no receive callback function was set for this raw PCB */
|
|
||||||
}
|
|
||||||
/* drop the packet */
|
|
||||||
prev = pcb;
|
|
||||||
pcb = pcb->next;
|
|
||||||
}
|
|
||||||
return eaten;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind a RAW PCB.
|
|
||||||
*
|
|
||||||
* @param pcb RAW PCB to be bound with a local address ipaddr.
|
|
||||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
|
||||||
* bind to all local interfaces.
|
|
||||||
*
|
|
||||||
* @return lwIP error code.
|
|
||||||
* - ERR_OK. Successful. No error occurred.
|
|
||||||
* - ERR_USE. The specified IP address is already bound to by
|
|
||||||
* another RAW PCB.
|
|
||||||
*
|
|
||||||
* @see raw_disconnect()
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
|
||||||
{
|
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect an RAW PCB. This function is required by upper layers
|
|
||||||
* of lwip. Using the raw api you could use raw_sendto() instead
|
|
||||||
*
|
|
||||||
* This will associate the RAW PCB with the remote address.
|
|
||||||
*
|
|
||||||
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
|
|
||||||
* @param ipaddr remote IP address to connect with.
|
|
||||||
*
|
|
||||||
* @return lwIP error code
|
|
||||||
*
|
|
||||||
* @see raw_disconnect() and raw_sendto()
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
|
||||||
{
|
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the callback function for received packets that match the
|
|
||||||
* raw PCB's protocol and binding.
|
|
||||||
*
|
|
||||||
* The callback function MUST either
|
|
||||||
* - eat the packet by calling pbuf_free() and returning non-zero. The
|
|
||||||
* packet will not be passed to other raw PCBs or other protocol layers.
|
|
||||||
* - not free the packet, and return zero. The packet will be matched
|
|
||||||
* against further PCBs and/or forwarded to another protocol layers.
|
|
||||||
*
|
|
||||||
* @return non-zero if the packet was free()d, zero if the packet remains
|
|
||||||
* available for others.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
|
|
||||||
{
|
|
||||||
/* remember recv() callback and user data */
|
|
||||||
pcb->recv = recv;
|
|
||||||
pcb->recv_arg = recv_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the raw IP packet to the given address. Note that actually you cannot
|
|
||||||
* modify the IP headers (this is inconsistent with the receive callback where
|
|
||||||
* you actually get the IP headers), you can only specify the IP payload here.
|
|
||||||
* It requires some more changes in lwIP. (there will be a raw_send() function
|
|
||||||
* then.)
|
|
||||||
*
|
|
||||||
* @param pcb the raw pcb which to send
|
|
||||||
* @param p the IP payload to send
|
|
||||||
* @param ipaddr the destination address of the IP packet
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|
||||||
{
|
|
||||||
err_t err;
|
|
||||||
struct netif *netif;
|
|
||||||
const ip_addr_t *src_ip;
|
|
||||||
struct pbuf *q; /* q will be sent down the stack */
|
|
||||||
s16_t header_size;
|
|
||||||
const ip_addr_t *dst_ip = ipaddr;
|
|
||||||
|
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
|
||||||
|
|
||||||
header_size = (
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN);
|
|
||||||
#elif LWIP_IPV4
|
|
||||||
IP_HLEN);
|
|
||||||
#else
|
|
||||||
IP6_HLEN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
|
||||||
if (pbuf_header(p, header_size)) {
|
|
||||||
/* allocate header in new pbuf */
|
|
||||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
|
||||||
/* new header pbuf could not be allocated? */
|
|
||||||
if (q == NULL) {
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
if (p->tot_len != 0) {
|
|
||||||
/* chain header q in front of given pbuf p */
|
|
||||||
pbuf_chain(q, p);
|
|
||||||
}
|
|
||||||
/* { first pbuf q points to header pbuf } */
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
|
||||||
} else {
|
|
||||||
/* first pbuf q equals given pbuf */
|
|
||||||
q = p;
|
|
||||||
if (pbuf_header(q, -header_size)) {
|
|
||||||
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
netif = ip_route(&pcb->local_ip, dst_ip);
|
|
||||||
if (netif == NULL) {
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
|
|
||||||
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
|
|
||||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
|
||||||
if (q != p) {
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
return ERR_RTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IP_SOF_BROADCAST
|
|
||||||
if (!IP_IS_V6(ipaddr))
|
|
||||||
{
|
|
||||||
/* broadcast filter? */
|
|
||||||
if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) {
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
|
||||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
|
||||||
if (q != p) {
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
return ERR_VAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* IP_SOF_BROADCAST */
|
|
||||||
|
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
|
||||||
/* use outgoing network interface IP address as source address */
|
|
||||||
src_ip = ip_netif_get_local_ip(netif, dst_ip);
|
|
||||||
#if LWIP_IPV6
|
|
||||||
if (src_ip == NULL) {
|
|
||||||
if (q != p) {
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
return ERR_RTE;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
} else {
|
|
||||||
/* use RAW PCB local IP address as source address */
|
|
||||||
src_ip = &pcb->local_ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
|
|
||||||
compute the checksum and update the checksum in the payload. */
|
|
||||||
if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) {
|
|
||||||
u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
|
|
||||||
LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
|
|
||||||
SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
|
||||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
|
||||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
|
||||||
|
|
||||||
/* did we chain a header earlier? */
|
|
||||||
if (q != p) {
|
|
||||||
/* free the header */
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the raw IP packet to the address given by raw_connect()
|
|
||||||
*
|
|
||||||
* @param pcb the raw pcb which to send
|
|
||||||
* @param p the IP payload to send
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
err_t
|
|
||||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
|
||||||
{
|
|
||||||
return raw_sendto(pcb, p, &pcb->remote_ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an RAW PCB.
|
|
||||||
*
|
|
||||||
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
|
|
||||||
* RAW PCB's and the data structure is freed from memory.
|
|
||||||
*
|
|
||||||
* @see raw_new()
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
raw_remove(struct raw_pcb *pcb)
|
|
||||||
{
|
|
||||||
struct raw_pcb *pcb2;
|
|
||||||
/* pcb to be removed is first in list? */
|
|
||||||
if (raw_pcbs == pcb) {
|
|
||||||
/* make list start at 2nd pcb */
|
|
||||||
raw_pcbs = raw_pcbs->next;
|
|
||||||
/* pcb not 1st in list */
|
|
||||||
} else {
|
|
||||||
for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
|
||||||
/* find pcb in raw_pcbs list */
|
|
||||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
|
||||||
/* remove pcb from list */
|
|
||||||
pcb2->next = pcb->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memp_free(MEMP_RAW_PCB, pcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a RAW PCB.
|
|
||||||
*
|
|
||||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
|
||||||
* could not be allocated.
|
|
||||||
*
|
|
||||||
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
|
|
||||||
*
|
|
||||||
* @see raw_remove()
|
|
||||||
*/
|
|
||||||
struct raw_pcb *
|
|
||||||
raw_new(u8_t proto)
|
|
||||||
{
|
|
||||||
struct raw_pcb *pcb;
|
|
||||||
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
|
|
||||||
|
|
||||||
pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
|
|
||||||
/* could allocate RAW PCB? */
|
|
||||||
if (pcb != NULL) {
|
|
||||||
/* initialize PCB to all zeroes */
|
|
||||||
memset(pcb, 0, sizeof(struct raw_pcb));
|
|
||||||
pcb->protocol = proto;
|
|
||||||
pcb->ttl = RAW_TTL;
|
|
||||||
pcb->next = raw_pcbs;
|
|
||||||
raw_pcbs = pcb;
|
|
||||||
}
|
|
||||||
return pcb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a RAW PCB for IPv6.
|
|
||||||
*
|
|
||||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
|
||||||
* could not be allocated.
|
|
||||||
*
|
|
||||||
* @param type IP address type, see IPADDR_TYPE_XX definitions.
|
|
||||||
* @param proto the protocol number (next header) of the IPv6 packet payload
|
|
||||||
* (e.g. IP6_NEXTH_ICMP6)
|
|
||||||
*
|
|
||||||
* @see raw_remove()
|
|
||||||
*/
|
|
||||||
struct raw_pcb *
|
|
||||||
raw_new_ip_type(u8_t type, u8_t proto)
|
|
||||||
{
|
|
||||||
struct raw_pcb *pcb;
|
|
||||||
pcb = raw_new(proto);
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
if(pcb != NULL) {
|
|
||||||
IP_SET_TYPE_VAL(pcb->local_ip, type);
|
|
||||||
IP_SET_TYPE_VAL(pcb->remote_ip, type);
|
|
||||||
}
|
|
||||||
#else /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
LWIP_UNUSED_ARG(type);
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
return pcb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_RAW */
|
|
|
@ -1,202 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Statistics module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/debug.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct stats_ lwip_stats;
|
|
||||||
|
|
||||||
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
|
|
||||||
#if MEMP_STATS
|
|
||||||
static const char * memp_names[] = {
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) desc,
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
};
|
|
||||||
#endif /* MEMP_STATS */
|
|
||||||
#endif /* LWIP_DEBUG || LWIP_STATS_DISPLAY */
|
|
||||||
|
|
||||||
void
|
|
||||||
stats_init(void)
|
|
||||||
{
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
#if MEMP_STATS
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MEMP_MAX; i++) {
|
|
||||||
lwip_stats.memp[i].name = memp_names[i];
|
|
||||||
}
|
|
||||||
#endif /* MEMP_STATS */
|
|
||||||
#if MEM_STATS
|
|
||||||
lwip_stats.mem.name = "MEM";
|
|
||||||
#endif /* MEM_STATS */
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_STATS_DISPLAY
|
|
||||||
void
|
|
||||||
stats_display_proto(struct stats_proto *proto, const char *name)
|
|
||||||
{
|
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
|
||||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
|
|
||||||
LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
|
|
||||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
|
|
||||||
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr));
|
|
||||||
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr));
|
|
||||||
LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr));
|
|
||||||
LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err));
|
|
||||||
LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IGMP_STATS || MLD6_STATS
|
|
||||||
void
|
|
||||||
stats_display_igmp(struct stats_igmp *igmp, const char *name)
|
|
||||||
{
|
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
|
||||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
|
||||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
|
||||||
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
|
|
||||||
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
|
|
||||||
LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
|
|
||||||
LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group));
|
|
||||||
LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general));
|
|
||||||
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
|
|
||||||
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
|
|
||||||
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
|
|
||||||
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
|
|
||||||
}
|
|
||||||
#endif /* IGMP_STATS || MLD6_STATS */
|
|
||||||
|
|
||||||
#if MEM_STATS || MEMP_STATS
|
|
||||||
void
|
|
||||||
stats_display_mem(struct stats_mem *mem, const char *name)
|
|
||||||
{
|
|
||||||
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
|
||||||
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
|
||||||
LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used));
|
|
||||||
LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max));
|
|
||||||
LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MEMP_STATS
|
|
||||||
void
|
|
||||||
stats_display_memp(struct stats_mem *mem, int index)
|
|
||||||
{
|
|
||||||
if (index < MEMP_MAX) {
|
|
||||||
stats_display_mem(mem, memp_names[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* MEMP_STATS */
|
|
||||||
#endif /* MEM_STATS || MEMP_STATS */
|
|
||||||
|
|
||||||
#if SYS_STATS
|
|
||||||
void
|
|
||||||
stats_display_sys(struct stats_sys *sys)
|
|
||||||
{
|
|
||||||
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
|
|
||||||
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
|
||||||
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
|
||||||
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
|
||||||
LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used));
|
|
||||||
LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max));
|
|
||||||
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
|
|
||||||
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
|
||||||
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
|
||||||
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
|
|
||||||
}
|
|
||||||
#endif /* SYS_STATS */
|
|
||||||
|
|
||||||
void
|
|
||||||
stats_display(void)
|
|
||||||
{
|
|
||||||
s16_t i;
|
|
||||||
|
|
||||||
LINK_STATS_DISPLAY();
|
|
||||||
ETHARP_STATS_DISPLAY();
|
|
||||||
IPFRAG_STATS_DISPLAY();
|
|
||||||
IP6_FRAG_STATS_DISPLAY();
|
|
||||||
IP_STATS_DISPLAY();
|
|
||||||
ND6_STATS_DISPLAY();
|
|
||||||
IP6_STATS_DISPLAY();
|
|
||||||
IGMP_STATS_DISPLAY();
|
|
||||||
MLD6_STATS_DISPLAY();
|
|
||||||
ICMP_STATS_DISPLAY();
|
|
||||||
ICMP6_STATS_DISPLAY();
|
|
||||||
UDP_STATS_DISPLAY();
|
|
||||||
TCP_STATS_DISPLAY();
|
|
||||||
MEM_STATS_DISPLAY();
|
|
||||||
for (i = 0; i < MEMP_MAX; i++) {
|
|
||||||
MEMP_STATS_DISPLAY(i);
|
|
||||||
}
|
|
||||||
SYS_STATS_DISPLAY();
|
|
||||||
}
|
|
||||||
#endif /* LWIP_STATS_DISPLAY */
|
|
||||||
|
|
||||||
#if ESP_STATS_DROP
|
|
||||||
void stats_display_esp(struct stats_esp *esp)
|
|
||||||
{
|
|
||||||
LWIP_PLATFORM_DIAG(("\nESP\n\t"));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.rx_rawmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_rawmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.rx_udpmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_udpmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.rx_tcpmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_tcpmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.err_tcp_rxmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->err_tcp_rxmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.err_tcp_acceptmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->err_tcp_acceptmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.acceptmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->acceptmbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.free_mbox_post_fail: %"U32_F"\n\t", (u32_t)esp->free_mbox_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.tcpip_inpkt_post_fail: %"U32_F"\n\t", (u32_t)esp->tcpip_inpkt_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.tcpip_cb_post_fail: %"U32_F"\n\t", (u32_t)esp->tcpip_cb_post_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.wlanif_input_pbuf_fail: %"U32_F"\n\t", (u32_t)esp->wlanif_input_pbuf_fail));
|
|
||||||
LWIP_PLATFORM_DIAG(("esp.wlanif_outut_pbuf_fail: %"U32_F"\n\t", (u32_t)esp->wlanif_outut_pbuf_fail));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_STATS */
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* lwIP Operating System abstraction
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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/sys.h"
|
|
||||||
|
|
||||||
/* Most of the functions defined in sys.h must be implemented in the
|
|
||||||
* architecture-dependent file sys_arch.c */
|
|
||||||
|
|
||||||
#if !NO_SYS
|
|
||||||
|
|
||||||
#ifndef sys_msleep
|
|
||||||
/**
|
|
||||||
* Sleep for some ms. Timeouts are NOT processed while sleeping.
|
|
||||||
*
|
|
||||||
* @param ms number of milliseconds to sleep
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sys_msleep(u32_t ms)
|
|
||||||
{
|
|
||||||
if (ms > 0) {
|
|
||||||
sys_sem_t delaysem;
|
|
||||||
err_t err = sys_sem_new(&delaysem, 0);
|
|
||||||
if (err == ERR_OK) {
|
|
||||||
sys_arch_sem_wait(&delaysem, ms);
|
|
||||||
sys_sem_free(&delaysem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* sys_msleep */
|
|
||||||
|
|
||||||
#endif /* !NO_SYS */
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,439 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Stack-internal timers implementation.
|
|
||||||
* This file includes timer callbacks for stack-internal timers as well as
|
|
||||||
* functions to set up or stop timers and check for expired timers.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
* Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#include "lwip/timers.h"
|
|
||||||
#include "lwip/priv/tcp_priv.h"
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
|
|
||||||
#include "lwip/ip_frag.h"
|
|
||||||
#include "netif/etharp.h"
|
|
||||||
#include "lwip/dhcp.h"
|
|
||||||
#include "lwip/autoip.h"
|
|
||||||
#include "lwip/igmp.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
#include "lwip/nd6.h"
|
|
||||||
#include "lwip/ip6_frag.h"
|
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
|
|
||||||
#if LWIP_DEBUG_TIMERNAMES
|
|
||||||
#define HANDLER(x) x, #x
|
|
||||||
#else /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
#define HANDLER(x) x
|
|
||||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
|
|
||||||
#if ESP_DHCP
|
|
||||||
extern void dhcps_coarse_tmr(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** This array contains all stack-internal cyclic timers. To get the number of
|
|
||||||
* timers, use LWIP_ARRAYSIZE() */
|
|
||||||
const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
|
|
||||||
#if LWIP_TCP
|
|
||||||
/* The TCP timer is a special case: it does not have to run always and
|
|
||||||
* is triggered to start from TCP using tcp_timer_needed() */
|
|
||||||
{TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if LWIP_IPV4
|
|
||||||
#if IP_REASSEMBLY
|
|
||||||
{IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
|
|
||||||
#endif /* IP_REASSEMBLY */
|
|
||||||
#if LWIP_ARP
|
|
||||||
{ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
|
|
||||||
#endif /* LWIP_ARP */
|
|
||||||
#if LWIP_DHCP
|
|
||||||
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
|
|
||||||
{DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
|
|
||||||
#if ESP_DHCP
|
|
||||||
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcps_coarse_tmr)},
|
|
||||||
#endif
|
|
||||||
#endif /* LWIP_DHCP */
|
|
||||||
#if LWIP_AUTOIP
|
|
||||||
{AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)},
|
|
||||||
#endif /* LWIP_AUTOIP */
|
|
||||||
#if LWIP_IGMP
|
|
||||||
{IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
|
|
||||||
#endif /* LWIP_IGMP */
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#if LWIP_DNS
|
|
||||||
{DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
#if LWIP_IPV6
|
|
||||||
{ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
|
|
||||||
#if LWIP_IPV6_REASS
|
|
||||||
{IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
|
|
||||||
#endif /* LWIP_IPV6_REASS */
|
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
{MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
|
|
||||||
#endif /* LWIP_IPV6_MLD */
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
|
|
||||||
|
|
||||||
/** The one and only timeout list */
|
|
||||||
static struct sys_timeo *next_timeout;
|
|
||||||
static u32_t timeouts_last_time;
|
|
||||||
|
|
||||||
#if LWIP_TCP
|
|
||||||
/** global variable that shows if the tcp timer is currently scheduled or not */
|
|
||||||
static int tcpip_tcp_timer_active;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer callback function that calls tcp_tmr() and reschedules itself.
|
|
||||||
*
|
|
||||||
* @param arg unused argument
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
tcpip_tcp_timer(void *arg)
|
|
||||||
{
|
|
||||||
LWIP_UNUSED_ARG(arg);
|
|
||||||
|
|
||||||
/* call TCP timer handler */
|
|
||||||
tcp_tmr();
|
|
||||||
/* timer still needed? */
|
|
||||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
|
||||||
/* restart timer */
|
|
||||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
|
||||||
} else {
|
|
||||||
/* disable timer */
|
|
||||||
tcpip_tcp_timer_active = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from TCP_REG when registering a new PCB:
|
|
||||||
* the reason is to have the TCP timer only running when
|
|
||||||
* there are active (or time-wait) PCBs.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
tcp_timer_needed(void)
|
|
||||||
{
|
|
||||||
/* timer is off but needed again? */
|
|
||||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
|
||||||
/* enable and start timer */
|
|
||||||
tcpip_tcp_timer_active = 1;
|
|
||||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer callback function that calls mld6_tmr() and reschedules itself.
|
|
||||||
*
|
|
||||||
* @param arg unused argument
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
cyclic_timer(void *arg)
|
|
||||||
{
|
|
||||||
const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg;
|
|
||||||
#if LWIP_DEBUG_TIMERNAMES
|
|
||||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name));
|
|
||||||
#endif
|
|
||||||
cyclic->handler();
|
|
||||||
sys_timeout(cyclic->interval_ms, cyclic_timer, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initialize this module */
|
|
||||||
void sys_timeouts_init(void)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
/* tcp_tmr() at index 0 is started on demand */
|
|
||||||
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
|
||||||
/* we have to cast via size_t to get rid of const warning
|
|
||||||
* (this is OK as cyclic_timer() casts back to const* */
|
|
||||||
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise timestamp for sys_check_timeouts */
|
|
||||||
timeouts_last_time = sys_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a one-shot timer (aka timeout). Timeouts are processed in the
|
|
||||||
* following cases:
|
|
||||||
* - while waiting for a message using sys_timeouts_mbox_fetch()
|
|
||||||
* - by calling sys_check_timeouts() (NO_SYS==1 only)
|
|
||||||
*
|
|
||||||
* @param msecs time in milliseconds after that the timer should expire
|
|
||||||
* @param handler callback function to call when msecs have elapsed
|
|
||||||
* @param arg argument to pass to the callback function
|
|
||||||
*/
|
|
||||||
#if LWIP_DEBUG_TIMERNAMES
|
|
||||||
void
|
|
||||||
sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
|
|
||||||
#else /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
void
|
|
||||||
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
|
|
||||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
{
|
|
||||||
struct sys_timeo *timeout, *t;
|
|
||||||
u32_t now, diff;
|
|
||||||
|
|
||||||
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
|
|
||||||
if (timeout == NULL) {
|
|
||||||
LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
now = sys_now();
|
|
||||||
if (next_timeout == NULL) {
|
|
||||||
diff = 0;
|
|
||||||
timeouts_last_time = now;
|
|
||||||
} else {
|
|
||||||
diff = now - timeouts_last_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout->next = NULL;
|
|
||||||
timeout->h = handler;
|
|
||||||
timeout->arg = arg;
|
|
||||||
timeout->time = msecs + diff;
|
|
||||||
#if LWIP_DEBUG_TIMERNAMES
|
|
||||||
timeout->handler_name = handler_name;
|
|
||||||
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
|
|
||||||
(void *)timeout, msecs, handler_name, (void *)arg));
|
|
||||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
|
|
||||||
if (next_timeout == NULL) {
|
|
||||||
next_timeout = timeout;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_timeout->time > msecs) {
|
|
||||||
next_timeout->time -= msecs;
|
|
||||||
timeout->next = next_timeout;
|
|
||||||
next_timeout = timeout;
|
|
||||||
} else {
|
|
||||||
for (t = next_timeout; t != NULL; t = t->next) {
|
|
||||||
timeout->time -= t->time;
|
|
||||||
if (t->next == NULL || t->next->time > timeout->time) {
|
|
||||||
if (t->next != NULL) {
|
|
||||||
t->next->time -= timeout->time;
|
|
||||||
} else if (timeout->time > msecs) {
|
|
||||||
/* If this is the case, 'timeouts_last_time' and 'now' differs too much.
|
|
||||||
* This can be due to sys_check_timeouts() not being called at the right
|
|
||||||
* times, but also when stopping in a breakpoint. Anyway, let's assume
|
|
||||||
* this is not wanted, so add the first timer's time instead of 'diff' */
|
|
||||||
timeout->time = msecs + next_timeout->time;
|
|
||||||
}
|
|
||||||
timeout->next = t->next;
|
|
||||||
t->next = timeout;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go through timeout list (for this task only) and remove the first matching
|
|
||||||
* entry (subsequent entries remain untouched), even though the timeout has not
|
|
||||||
* triggered yet.
|
|
||||||
*
|
|
||||||
* @param handler callback function that would be called by the timeout
|
|
||||||
* @param arg callback argument that would be passed to handler
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sys_untimeout(sys_timeout_handler handler, void *arg)
|
|
||||||
{
|
|
||||||
struct sys_timeo *prev_t, *t;
|
|
||||||
|
|
||||||
if (next_timeout == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
|
|
||||||
if ((t->h == handler) && (t->arg == arg)) {
|
|
||||||
/* We have a match */
|
|
||||||
/* Unlink from previous in list */
|
|
||||||
if (prev_t == NULL) {
|
|
||||||
next_timeout = t->next;
|
|
||||||
} else {
|
|
||||||
prev_t->next = t->next;
|
|
||||||
}
|
|
||||||
/* If not the last one, add time of this one back to next */
|
|
||||||
if (t->next != NULL) {
|
|
||||||
t->next->time += t->time;
|
|
||||||
}
|
|
||||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup lwip_nosys
|
|
||||||
* Handle timeouts for NO_SYS==1 (i.e. without using
|
|
||||||
* tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
|
|
||||||
* handler functions when timeouts expire.
|
|
||||||
*
|
|
||||||
* Must be called periodically from your main loop.
|
|
||||||
*/
|
|
||||||
#if !NO_SYS && !defined __DOXYGEN__
|
|
||||||
static
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
void
|
|
||||||
sys_check_timeouts(void)
|
|
||||||
{
|
|
||||||
if (next_timeout) {
|
|
||||||
struct sys_timeo *tmptimeout;
|
|
||||||
u32_t diff;
|
|
||||||
sys_timeout_handler handler;
|
|
||||||
void *arg;
|
|
||||||
u8_t had_one;
|
|
||||||
u32_t now;
|
|
||||||
|
|
||||||
now = sys_now();
|
|
||||||
/* this cares for wraparounds */
|
|
||||||
diff = now - timeouts_last_time;
|
|
||||||
do {
|
|
||||||
PBUF_CHECK_FREE_OOSEQ();
|
|
||||||
had_one = 0;
|
|
||||||
tmptimeout = next_timeout;
|
|
||||||
if (tmptimeout && (tmptimeout->time <= diff)) {
|
|
||||||
/* timeout has expired */
|
|
||||||
had_one = 1;
|
|
||||||
timeouts_last_time += tmptimeout->time;
|
|
||||||
diff -= tmptimeout->time;
|
|
||||||
next_timeout = tmptimeout->next;
|
|
||||||
handler = tmptimeout->h;
|
|
||||||
arg = tmptimeout->arg;
|
|
||||||
#if LWIP_DEBUG_TIMERNAMES
|
|
||||||
if (handler != NULL) {
|
|
||||||
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",tmptimeout->handler_name, arg));
|
|
||||||
}
|
|
||||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
|
||||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
|
||||||
if (handler != NULL) {
|
|
||||||
#if !NO_SYS
|
|
||||||
/* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
|
|
||||||
* timeout handler function. */
|
|
||||||
LOCK_TCPIP_CORE();
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
handler(arg);
|
|
||||||
#if !NO_SYS
|
|
||||||
UNLOCK_TCPIP_CORE();
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
}
|
|
||||||
LWIP_TCPIP_THREAD_ALIVE();
|
|
||||||
}
|
|
||||||
/* repeat until all expired timers have been called */
|
|
||||||
} while (had_one);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set back the timestamp of the last call to sys_check_timeouts()
|
|
||||||
* This is necessary if sys_check_timeouts() hasn't been called for a long
|
|
||||||
* time (e.g. while saving energy) to prevent all timer functions of that
|
|
||||||
* period being called.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sys_restart_timeouts(void)
|
|
||||||
{
|
|
||||||
timeouts_last_time = sys_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the time left before the next timeout is due. If no timeouts are
|
|
||||||
* enqueued, returns 0xffffffff
|
|
||||||
*/
|
|
||||||
#if !NO_SYS
|
|
||||||
static
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
u32_t
|
|
||||||
sys_timeouts_sleeptime(void)
|
|
||||||
{
|
|
||||||
u32_t diff;
|
|
||||||
if (next_timeout == NULL) {
|
|
||||||
return 0xffffffff;
|
|
||||||
}
|
|
||||||
diff = sys_now() - timeouts_last_time;
|
|
||||||
if (diff > next_timeout->time) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return next_timeout->time - diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !NO_SYS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait (forever) for a message to arrive in an mbox.
|
|
||||||
* While waiting, timeouts are processed.
|
|
||||||
*
|
|
||||||
* @param mbox the mbox to fetch the message from
|
|
||||||
* @param msg the place to store the message
|
|
||||||
*/
|
|
||||||
void ESP_IRAM_ATTR
|
|
||||||
sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
|
|
||||||
{
|
|
||||||
u32_t sleeptime;
|
|
||||||
again:
|
|
||||||
if (!next_timeout) {
|
|
||||||
sys_arch_mbox_fetch(mbox, msg, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleeptime = sys_timeouts_sleeptime();
|
|
||||||
if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) {
|
|
||||||
/* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
|
|
||||||
* before a message could be fetched. */
|
|
||||||
sys_check_timeouts();
|
|
||||||
/* We try again to fetch a message from the mbox. */
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NO_SYS */
|
|
||||||
|
|
||||||
#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
|
|
||||||
/* Satisfy the TCP code which calls this function */
|
|
||||||
void
|
|
||||||
tcp_timer_needed(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
|
|
||||||
* 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: Frédéric Bernon, Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_APPS_SNTP_H
|
|
||||||
#define LWIP_HDR_APPS_SNTP_H
|
|
||||||
|
|
||||||
#include "apps/sntp/sntp_opts.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* SNTP operating modes: default is to poll using unicast.
|
|
||||||
The mode has to be set before calling sntp_init(). */
|
|
||||||
#define SNTP_OPMODE_POLL 0
|
|
||||||
#define SNTP_OPMODE_LISTENONLY 1
|
|
||||||
void sntp_setoperatingmode(u8_t operating_mode);
|
|
||||||
u8_t sntp_getoperatingmode(void);
|
|
||||||
|
|
||||||
void sntp_init(void);
|
|
||||||
void sntp_stop(void);
|
|
||||||
u8_t sntp_enabled(void);
|
|
||||||
|
|
||||||
void sntp_setserver(u8_t idx, const ip_addr_t *addr);
|
|
||||||
ip_addr_t sntp_getserver(u8_t idx);
|
|
||||||
|
|
||||||
#if SNTP_SERVER_DNS
|
|
||||||
void sntp_setservername(u8_t idx, char *server);
|
|
||||||
char *sntp_getservername(u8_t idx);
|
|
||||||
#endif /* SNTP_SERVER_DNS */
|
|
||||||
|
|
||||||
#if SNTP_GET_SERVERS_FROM_DHCP
|
|
||||||
void sntp_servermode_dhcp(int set_servers_from_dhcp);
|
|
||||||
#else /* SNTP_GET_SERVERS_FROM_DHCP */
|
|
||||||
#define sntp_servermode_dhcp(x)
|
|
||||||
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_APPS_SNTP_H */
|
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
|
|
||||||
* 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: Frédéric Bernon, Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_APPS_SNTP_OPTS_H
|
|
||||||
#define LWIP_HDR_APPS_SNTP_OPTS_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
/** SNTP macro to change system time in seconds
|
|
||||||
* Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one
|
|
||||||
* if you need the additional precision.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_SET_SYSTEM_TIME
|
|
||||||
#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** The maximum number of SNTP servers that can be set */
|
|
||||||
#ifndef SNTP_MAX_SERVERS
|
|
||||||
#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Set this to 1 to implement the callback function called by dhcp when
|
|
||||||
* NTP servers are received. */
|
|
||||||
#ifndef SNTP_GET_SERVERS_FROM_DHCP
|
|
||||||
#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set this to 1 to support DNS names (or IP address strings) to set sntp servers */
|
|
||||||
#ifndef SNTP_SERVER_DNS
|
|
||||||
#define SNTP_SERVER_DNS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** One server address/name can be defined as default if SNTP_SERVER_DNS == 1:
|
|
||||||
* #define SNTP_SERVER_ADDRESS "pool.ntp.org"
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SNTP_DEBUG: Enable debugging for SNTP.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_DEBUG
|
|
||||||
#define SNTP_DEBUG LWIP_DBG_OFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** SNTP server port */
|
|
||||||
#ifndef SNTP_PORT
|
|
||||||
#define SNTP_PORT 123
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Set this to 1 to allow config of SNTP server(s) by DNS name */
|
|
||||||
#ifndef SNTP_SERVER_DNS
|
|
||||||
#define SNTP_SERVER_DNS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Sanity check:
|
|
||||||
* Define this to
|
|
||||||
* - 0 to turn off sanity checks (default; smaller code)
|
|
||||||
* - >= 1 to check address and port of the response packet to ensure the
|
|
||||||
* response comes from the server we sent the request to.
|
|
||||||
* - >= 2 to check returned Originate Timestamp against Transmit Timestamp
|
|
||||||
* sent to the server (to ensure response to older request).
|
|
||||||
* - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp
|
|
||||||
* fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast).
|
|
||||||
* - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each
|
|
||||||
* greater than or equal to 0 and less than infinity, where infinity is
|
|
||||||
* currently a cozy number like one second. This check avoids using a
|
|
||||||
* server whose synchronization source has expired for a very long time.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_CHECK_RESPONSE
|
|
||||||
#define SNTP_CHECK_RESPONSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** According to the RFC, this shall be a random delay
|
|
||||||
* between 1 and 5 minutes (in milliseconds) to prevent load peaks.
|
|
||||||
* This can be defined to a random generation function,
|
|
||||||
* which must return the delay in milliseconds as u32_t.
|
|
||||||
* Turned off by default.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_STARTUP_DELAY
|
|
||||||
#define SNTP_STARTUP_DELAY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** If you want the startup delay to be a function, define this
|
|
||||||
* to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_STARTUP_DELAY_FUNC
|
|
||||||
#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** SNTP receive timeout - in milliseconds
|
|
||||||
* Also used as retry timeout - this shouldn't be too low.
|
|
||||||
* Default is 3 seconds.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_RECV_TIMEOUT
|
|
||||||
#define SNTP_RECV_TIMEOUT 3000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** SNTP update delay - in milliseconds
|
|
||||||
* Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000)
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_UPDATE_DELAY
|
|
||||||
#define SNTP_UPDATE_DELAY 3600000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
|
|
||||||
* to send in request and compare in response.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_GET_SYSTEM_TIME
|
|
||||||
#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Default retry timeout (in milliseconds) if the response
|
|
||||||
* received is invalid.
|
|
||||||
* This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_RETRY_TIMEOUT
|
|
||||||
#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Maximum retry timeout (in milliseconds). */
|
|
||||||
#ifndef SNTP_RETRY_TIMEOUT_MAX
|
|
||||||
#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Increase retry timeout with every retry sent
|
|
||||||
* Default is on to conform to RFC.
|
|
||||||
*/
|
|
||||||
#ifndef SNTP_RETRY_TIMEOUT_EXP
|
|
||||||
#define SNTP_RETRY_TIMEOUT_EXP 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */
|
|
|
@ -1,364 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_API_H
|
|
||||||
#define LWIP_HDR_API_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
|
||||||
/* Note: Netconn API is always available when sockets are enabled -
|
|
||||||
* sockets are implemented on top of them */
|
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
|
||||||
|
|
||||||
#include "lwip/netbuf.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Throughout this file, IP addresses and port numbers are expected to be in
|
|
||||||
* the same byte order as in the corresponding pcb.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Flags for netconn_write (u8_t) */
|
|
||||||
#define NETCONN_NOFLAG 0x00
|
|
||||||
#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
|
|
||||||
#define NETCONN_COPY 0x01
|
|
||||||
#define NETCONN_MORE 0x02
|
|
||||||
#define NETCONN_DONTBLOCK 0x04
|
|
||||||
|
|
||||||
/* Flags for struct netconn.flags (u8_t) */
|
|
||||||
/** Should this netconn avoid blocking? */
|
|
||||||
#define NETCONN_FLAG_NON_BLOCKING 0x02
|
|
||||||
/** Was the last connect action a non-blocking one? */
|
|
||||||
#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
|
|
||||||
/** If this is set, a TCP netconn must call netconn_recved() to update
|
|
||||||
the TCP receive window (done automatically if not set). */
|
|
||||||
#define NETCONN_FLAG_NO_AUTO_RECVED 0x08
|
|
||||||
/** If a nonblocking write has been rejected before, poll_tcp needs to
|
|
||||||
check if the netconn is writable again */
|
|
||||||
#define NETCONN_FLAG_CHECK_WRITESPACE 0x10
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** If this flag is set then only IPv6 communication is allowed on the
|
|
||||||
netconn. As per RFC#3493 this features defaults to OFF allowing
|
|
||||||
dual-stack usage by default. */
|
|
||||||
#define NETCONN_FLAG_IPV6_V6ONLY 0x20
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
|
|
||||||
/* Helpers to process several netconn_types by the same code */
|
|
||||||
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
|
|
||||||
#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0)
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#define NETCONN_TYPE_IPV6 0x08
|
|
||||||
#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0)
|
|
||||||
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
|
|
||||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
|
|
||||||
#else /* LWIP_IPV6 */
|
|
||||||
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
|
|
||||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/** Protocol family and type of the netconn */
|
|
||||||
enum netconn_type {
|
|
||||||
NETCONN_INVALID = 0,
|
|
||||||
/* NETCONN_TCP Group */
|
|
||||||
NETCONN_TCP = 0x10,
|
|
||||||
#if LWIP_IPV6
|
|
||||||
NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */,
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
/* NETCONN_UDP Group */
|
|
||||||
NETCONN_UDP = 0x20,
|
|
||||||
NETCONN_UDPLITE = 0x21,
|
|
||||||
NETCONN_UDPNOCHKSUM = 0x22,
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */,
|
|
||||||
NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */,
|
|
||||||
NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */,
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/* NETCONN_RAW Group */
|
|
||||||
NETCONN_RAW = 0x40
|
|
||||||
#if LWIP_IPV6
|
|
||||||
, NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Current state of the netconn. Non-TCP netconns are always
|
|
||||||
* in state NETCONN_NONE! */
|
|
||||||
enum netconn_state {
|
|
||||||
NETCONN_NONE,
|
|
||||||
NETCONN_WRITE,
|
|
||||||
NETCONN_LISTEN,
|
|
||||||
NETCONN_CONNECT,
|
|
||||||
NETCONN_CLOSE
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Use to inform the callback function about changes */
|
|
||||||
enum netconn_evt {
|
|
||||||
NETCONN_EVT_RCVPLUS,
|
|
||||||
NETCONN_EVT_RCVMINUS,
|
|
||||||
NETCONN_EVT_SENDPLUS,
|
|
||||||
NETCONN_EVT_SENDMINUS,
|
|
||||||
NETCONN_EVT_ERROR
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
|
||||||
/** Used for netconn_join_leave_group() */
|
|
||||||
enum netconn_igmp {
|
|
||||||
NETCONN_JOIN,
|
|
||||||
NETCONN_LEAVE
|
|
||||||
};
|
|
||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
|
||||||
|
|
||||||
#if LWIP_DNS
|
|
||||||
/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */
|
|
||||||
#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6
|
|
||||||
#define NETCONN_DNS_IPV4 0
|
|
||||||
#define NETCONN_DNS_IPV6 1
|
|
||||||
#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */
|
|
||||||
#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
|
|
||||||
/* forward-declare some structs to avoid to include their headers */
|
|
||||||
struct ip_pcb;
|
|
||||||
struct tcp_pcb;
|
|
||||||
struct udp_pcb;
|
|
||||||
struct raw_pcb;
|
|
||||||
struct netconn;
|
|
||||||
struct api_msg_msg;
|
|
||||||
|
|
||||||
/** A callback prototype to inform about events for a netconn */
|
|
||||||
typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len);
|
|
||||||
|
|
||||||
/** A netconn descriptor */
|
|
||||||
struct netconn {
|
|
||||||
/** type of the netconn (TCP, UDP or RAW) */
|
|
||||||
enum netconn_type type;
|
|
||||||
/** current state of the netconn */
|
|
||||||
enum netconn_state state;
|
|
||||||
/** the lwIP internal protocol control block */
|
|
||||||
union {
|
|
||||||
struct ip_pcb *ip;
|
|
||||||
struct tcp_pcb *tcp;
|
|
||||||
struct udp_pcb *udp;
|
|
||||||
struct raw_pcb *raw;
|
|
||||||
} pcb;
|
|
||||||
/** the last error this netconn had */
|
|
||||||
err_t last_err;
|
|
||||||
|
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
/** sem that is used to synchronously execute functions in the core context */
|
|
||||||
sys_sem_t op_completed;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** mbox where received packets are stored until they are fetched
|
|
||||||
by the netconn application thread (can grow quite big) */
|
|
||||||
sys_mbox_t recvmbox;
|
|
||||||
#if LWIP_TCP
|
|
||||||
/** mbox where new connections are stored until processed
|
|
||||||
by the application thread */
|
|
||||||
sys_mbox_t acceptmbox;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
/** only used for socket layer */
|
|
||||||
#if LWIP_SOCKET
|
|
||||||
int socket;
|
|
||||||
#endif /* LWIP_SOCKET */
|
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
/** timeout to wait for sending data (which means enqueueing data for sending
|
|
||||||
in internal buffers) in milliseconds */
|
|
||||||
s32_t send_timeout;
|
|
||||||
#endif /* LWIP_SO_RCVTIMEO */
|
|
||||||
#if LWIP_SO_RCVTIMEO
|
|
||||||
/** timeout in milliseconds to wait for new data to be received
|
|
||||||
(or connections to arrive for listening netconns) */
|
|
||||||
int recv_timeout;
|
|
||||||
#endif /* LWIP_SO_RCVTIMEO */
|
|
||||||
#if LWIP_SO_RCVBUF
|
|
||||||
/** maximum amount of bytes queued in recvmbox
|
|
||||||
not used for TCP: adjust TCP_WND instead! */
|
|
||||||
int recv_bufsize;
|
|
||||||
/** number of bytes currently in recvmbox to be received,
|
|
||||||
tested against recv_bufsize to limit bytes on recvmbox
|
|
||||||
for UDP and RAW, used for FIONREAD */
|
|
||||||
int recv_avail;
|
|
||||||
#endif /* LWIP_SO_RCVBUF */
|
|
||||||
#if LWIP_SO_LINGER
|
|
||||||
/** values <0 mean linger is disabled, values > 0 are seconds to linger */
|
|
||||||
s16_t linger;
|
|
||||||
#endif /* LWIP_SO_LINGER */
|
|
||||||
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
|
||||||
u8_t flags;
|
|
||||||
#if LWIP_TCP
|
|
||||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
|
||||||
this temporarily stores how much is already sent. */
|
|
||||||
size_t write_offset;
|
|
||||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
|
||||||
this temporarily stores the message.
|
|
||||||
Also used during connect and close. */
|
|
||||||
struct api_msg_msg *current_msg;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
/** A callback function that is informed about events for this netconn */
|
|
||||||
netconn_callback callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Register an Network connection event */
|
|
||||||
#define API_EVENT(c,e,l) if (c->callback) { \
|
|
||||||
(*c->callback)(c, e, l); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set conn->last_err to err but don't overwrite fatal errors */
|
|
||||||
#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \
|
|
||||||
SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \
|
|
||||||
SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \
|
|
||||||
if (!ERR_IS_FATAL((conn)->last_err)) { \
|
|
||||||
(conn)->last_err = err; \
|
|
||||||
} \
|
|
||||||
SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \
|
|
||||||
}} while(0);
|
|
||||||
|
|
||||||
/* Network connection functions: */
|
|
||||||
#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL)
|
|
||||||
#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
|
|
||||||
struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
|
|
||||||
netconn_callback callback);
|
|
||||||
err_t netconn_delete(struct netconn *conn);
|
|
||||||
/** Get the type of a netconn (as enum netconn_type). */
|
|
||||||
#define netconn_type(conn) (conn->type)
|
|
||||||
|
|
||||||
err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr,
|
|
||||||
u16_t *port, u8_t local);
|
|
||||||
#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0)
|
|
||||||
#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1)
|
|
||||||
|
|
||||||
err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port);
|
|
||||||
err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port);
|
|
||||||
err_t netconn_disconnect (struct netconn *conn);
|
|
||||||
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
|
|
||||||
#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
|
|
||||||
err_t netconn_accept(struct netconn *conn, struct netconn **new_conn);
|
|
||||||
err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf);
|
|
||||||
err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf);
|
|
||||||
void netconn_recved(struct netconn *conn, u32_t length);
|
|
||||||
err_t netconn_sendto(struct netconn *conn, struct netbuf *buf,
|
|
||||||
const ip_addr_t *addr, u16_t port);
|
|
||||||
err_t netconn_send(struct netconn *conn, struct netbuf *buf);
|
|
||||||
err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|
||||||
u8_t apiflags, size_t *bytes_written);
|
|
||||||
#define netconn_write(conn, dataptr, size, apiflags) \
|
|
||||||
netconn_write_partly(conn, dataptr, size, apiflags, NULL)
|
|
||||||
err_t netconn_close(struct netconn *conn);
|
|
||||||
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
|
|
||||||
|
|
||||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
|
||||||
err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr,
|
|
||||||
const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
|
|
||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
|
||||||
#if LWIP_DNS
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype);
|
|
||||||
#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT)
|
|
||||||
#else /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
|
||||||
#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr)
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
|
|
||||||
#define netconn_err(conn) ((conn)->last_err)
|
|
||||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
|
||||||
|
|
||||||
/** Set the blocking status of netconn calls (@todo: write/send is missing) */
|
|
||||||
#define netconn_set_nonblocking(conn, val) do { if(val) { \
|
|
||||||
(conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \
|
|
||||||
} else { \
|
|
||||||
(conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0)
|
|
||||||
/** Get the blocking status of netconn calls (@todo: write/send is missing) */
|
|
||||||
#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0)
|
|
||||||
|
|
||||||
/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
|
|
||||||
#define netconn_set_noautorecved(conn, val) do { if(val) { \
|
|
||||||
(conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \
|
|
||||||
} else { \
|
|
||||||
(conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0)
|
|
||||||
/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
|
|
||||||
#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0)
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) */
|
|
||||||
#define netconn_set_ipv6only(conn, val) do { if(val) { \
|
|
||||||
(conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \
|
|
||||||
} else { \
|
|
||||||
(conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0)
|
|
||||||
/** TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) */
|
|
||||||
#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0)
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
/** Set the send timeout in milliseconds */
|
|
||||||
#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout))
|
|
||||||
/** Get the send timeout in milliseconds */
|
|
||||||
#define netconn_get_sendtimeout(conn) ((conn)->send_timeout)
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO */
|
|
||||||
#if LWIP_SO_RCVTIMEO
|
|
||||||
/** Set the receive timeout in milliseconds */
|
|
||||||
#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))
|
|
||||||
/** Get the receive timeout in milliseconds */
|
|
||||||
#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout)
|
|
||||||
#endif /* LWIP_SO_RCVTIMEO */
|
|
||||||
#if LWIP_SO_RCVBUF
|
|
||||||
/** Set the receive buffer in bytes */
|
|
||||||
#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize))
|
|
||||||
/** Get the receive buffer in bytes */
|
|
||||||
#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize)
|
|
||||||
#endif /* LWIP_SO_RCVBUF*/
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
void netconn_thread_init(void);
|
|
||||||
void netconn_thread_cleanup(void);
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
#define netconn_thread_init()
|
|
||||||
#define netconn_thread_cleanup()
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_API_H */
|
|
|
@ -1,238 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_ARCH_H
|
|
||||||
#define LWIP_HDR_ARCH_H
|
|
||||||
|
|
||||||
#ifndef LITTLE_ENDIAN
|
|
||||||
#define LITTLE_ENDIAN 1234
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BIG_ENDIAN
|
|
||||||
#define BIG_ENDIAN 4321
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arch/cc.h"
|
|
||||||
|
|
||||||
/** Temporary: define format string for size_t if not defined in cc.h */
|
|
||||||
#ifndef SZT_F
|
|
||||||
#define SZT_F U32_F
|
|
||||||
#endif /* SZT_F */
|
|
||||||
/** Temporary upgrade helper: define format string for u8_t as hex if not
|
|
||||||
defined in cc.h */
|
|
||||||
#ifndef X8_F
|
|
||||||
#define X8_F "02x"
|
|
||||||
#endif /* X8_F */
|
|
||||||
|
|
||||||
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
|
|
||||||
#ifndef LWIP_CONST_CAST
|
|
||||||
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PACK_STRUCT_BEGIN
|
|
||||||
#define PACK_STRUCT_BEGIN
|
|
||||||
#endif /* PACK_STRUCT_BEGIN */
|
|
||||||
|
|
||||||
#ifndef PACK_STRUCT_END
|
|
||||||
#define PACK_STRUCT_END
|
|
||||||
#endif /* PACK_STRUCT_END */
|
|
||||||
|
|
||||||
#ifndef PACK_STRUCT_STRUCT
|
|
||||||
#define PACK_STRUCT_STRUCT
|
|
||||||
#endif /* PACK_STRUCT_STRUCT */
|
|
||||||
|
|
||||||
#ifndef PACK_STRUCT_FIELD
|
|
||||||
#define PACK_STRUCT_FIELD(x) x
|
|
||||||
#endif /* PACK_STRUCT_FIELD */
|
|
||||||
|
|
||||||
/* Used for struct fields of u8_t,
|
|
||||||
* where some compilers warn that packing is not necessary */
|
|
||||||
#ifndef PACK_STRUCT_FLD_8
|
|
||||||
#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x)
|
|
||||||
#endif /* PACK_STRUCT_FLD_8 */
|
|
||||||
|
|
||||||
/* Used for struct fields of that are packed structs themself,
|
|
||||||
* where some compilers warn that packing is not necessary */
|
|
||||||
#ifndef PACK_STRUCT_FLD_S
|
|
||||||
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
|
|
||||||
#endif /* PACK_STRUCT_FLD_S */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef LWIP_UNUSED_ARG
|
|
||||||
#define LWIP_UNUSED_ARG(x) (void)x
|
|
||||||
#endif /* LWIP_UNUSED_ARG */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LWIP_PROVIDE_ERRNO
|
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
|
||||||
#define ENOENT 2 /* No such file or directory */
|
|
||||||
#define ESRCH 3 /* No such process */
|
|
||||||
#define EINTR 4 /* Interrupted system call */
|
|
||||||
#define EIO 5 /* I/O error */
|
|
||||||
#define ENXIO 6 /* No such device or address */
|
|
||||||
#define E2BIG 7 /* Arg list too long */
|
|
||||||
#define ENOEXEC 8 /* Exec format error */
|
|
||||||
#define EBADF 9 /* Bad file number */
|
|
||||||
#define ECHILD 10 /* No child processes */
|
|
||||||
#define EAGAIN 11 /* Try again */
|
|
||||||
#define ENOMEM 12 /* Out of memory */
|
|
||||||
#define EACCES 13 /* Permission denied */
|
|
||||||
#define EFAULT 14 /* Bad address */
|
|
||||||
#define ENOTBLK 15 /* Block device required */
|
|
||||||
#define EBUSY 16 /* Device or resource busy */
|
|
||||||
#define EEXIST 17 /* File exists */
|
|
||||||
#define EXDEV 18 /* Cross-device link */
|
|
||||||
#define ENODEV 19 /* No such device */
|
|
||||||
#define ENOTDIR 20 /* Not a directory */
|
|
||||||
#define EISDIR 21 /* Is a directory */
|
|
||||||
#define EINVAL 22 /* Invalid argument */
|
|
||||||
#define ENFILE 23 /* File table overflow */
|
|
||||||
#define EMFILE 24 /* Too many open files */
|
|
||||||
#define ENOTTY 25 /* Not a typewriter */
|
|
||||||
#define ETXTBSY 26 /* Text file busy */
|
|
||||||
#define EFBIG 27 /* File too large */
|
|
||||||
#define ENOSPC 28 /* No space left on device */
|
|
||||||
#define ESPIPE 29 /* Illegal seek */
|
|
||||||
#define EROFS 30 /* Read-only file system */
|
|
||||||
#define EMLINK 31 /* Too many links */
|
|
||||||
#define EPIPE 32 /* Broken pipe */
|
|
||||||
#define EDOM 33 /* Math argument out of domain of func */
|
|
||||||
#define ERANGE 34 /* Math result not representable */
|
|
||||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
|
||||||
#define ENAMETOOLONG 36 /* File name too long */
|
|
||||||
#define ENOLCK 37 /* No record locks available */
|
|
||||||
#define ENOSYS 38 /* Function not implemented */
|
|
||||||
#define ENOTEMPTY 39 /* Directory not empty */
|
|
||||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
|
||||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
|
||||||
#define ENOMSG 42 /* No message of desired type */
|
|
||||||
#define EIDRM 43 /* Identifier removed */
|
|
||||||
#define ECHRNG 44 /* Channel number out of range */
|
|
||||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
|
||||||
#define EL3HLT 46 /* Level 3 halted */
|
|
||||||
#define EL3RST 47 /* Level 3 reset */
|
|
||||||
#define ELNRNG 48 /* Link number out of range */
|
|
||||||
#define EUNATCH 49 /* Protocol driver not attached */
|
|
||||||
#define ENOCSI 50 /* No CSI structure available */
|
|
||||||
#define EL2HLT 51 /* Level 2 halted */
|
|
||||||
#define EBADE 52 /* Invalid exchange */
|
|
||||||
#define EBADR 53 /* Invalid request descriptor */
|
|
||||||
#define EXFULL 54 /* Exchange full */
|
|
||||||
#define ENOANO 55 /* No anode */
|
|
||||||
#define EBADRQC 56 /* Invalid request code */
|
|
||||||
#define EBADSLT 57 /* Invalid slot */
|
|
||||||
|
|
||||||
#define EDEADLOCK EDEADLK
|
|
||||||
|
|
||||||
#define EBFONT 59 /* Bad font file format */
|
|
||||||
#define ENOSTR 60 /* Device not a stream */
|
|
||||||
#define ENODATA 61 /* No data available */
|
|
||||||
#define ETIME 62 /* Timer expired */
|
|
||||||
#define ENOSR 63 /* Out of streams resources */
|
|
||||||
#define ENONET 64 /* Machine is not on the network */
|
|
||||||
#define ENOPKG 65 /* Package not installed */
|
|
||||||
#define EREMOTE 66 /* Object is remote */
|
|
||||||
#define ENOLINK 67 /* Link has been severed */
|
|
||||||
#define EADV 68 /* Advertise error */
|
|
||||||
#define ESRMNT 69 /* Srmount error */
|
|
||||||
#define ECOMM 70 /* Communication error on send */
|
|
||||||
#define EPROTO 71 /* Protocol error */
|
|
||||||
#define EMULTIHOP 72 /* Multihop attempted */
|
|
||||||
#define EDOTDOT 73 /* RFS specific error */
|
|
||||||
#define EBADMSG 74 /* Not a data message */
|
|
||||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
|
||||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
|
||||||
#define EBADFD 77 /* File descriptor in bad state */
|
|
||||||
#define EREMCHG 78 /* Remote address changed */
|
|
||||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
|
||||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
|
||||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
|
||||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
|
||||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
|
||||||
#define EILSEQ 84 /* Illegal byte sequence */
|
|
||||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
|
||||||
#define ESTRPIPE 86 /* Streams pipe error */
|
|
||||||
#define EUSERS 87 /* Too many users */
|
|
||||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
|
||||||
#define EDESTADDRREQ 89 /* Destination address required */
|
|
||||||
#define EMSGSIZE 90 /* Message too long */
|
|
||||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
|
||||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
|
||||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
|
||||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
|
||||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
|
||||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
|
||||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
|
||||||
#define EADDRINUSE 98 /* Address already in use */
|
|
||||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
|
||||||
#define ENETDOWN 100 /* Network is down */
|
|
||||||
#define ENETUNREACH 101 /* Network is unreachable */
|
|
||||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
|
||||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
|
||||||
#define ECONNRESET 104 /* Connection reset by peer */
|
|
||||||
#define ENOBUFS 105 /* No buffer space available */
|
|
||||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
|
||||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
|
||||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
|
||||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
|
||||||
#define ETIMEDOUT 110 /* Connection timed out */
|
|
||||||
#define ECONNREFUSED 111 /* Connection refused */
|
|
||||||
#define EHOSTDOWN 112 /* Host is down */
|
|
||||||
#define EHOSTUNREACH 113 /* No route to host */
|
|
||||||
#define EALREADY 114 /* Operation already in progress */
|
|
||||||
#define EINPROGRESS 115 /* Operation now in progress */
|
|
||||||
#define ESTALE 116 /* Stale NFS file handle */
|
|
||||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
|
||||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
|
||||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
|
||||||
#define EISNAM 120 /* Is a named type file */
|
|
||||||
#define EREMOTEIO 121 /* Remote I/O error */
|
|
||||||
#define EDQUOT 122 /* Quota exceeded */
|
|
||||||
|
|
||||||
#define ENOMEDIUM 123 /* No medium found */
|
|
||||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
|
||||||
|
|
||||||
#ifndef errno
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_PROVIDE_ERRNO */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ARCH_H */
|
|
|
@ -1,124 +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>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_AUTOIP_H
|
|
||||||
#define LWIP_HDR_AUTOIP_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
/* #include "lwip/udp.h" */
|
|
||||||
#include "netif/etharp.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* AutoIP Timing */
|
|
||||||
#define AUTOIP_TMR_INTERVAL 100
|
|
||||||
#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL)
|
|
||||||
|
|
||||||
/* RFC 3927 Constants */
|
|
||||||
#define PROBE_WAIT 1 /* second (initial random delay) */
|
|
||||||
#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */
|
|
||||||
#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */
|
|
||||||
#define PROBE_NUM 3 /* (number of probe packets) */
|
|
||||||
#define ANNOUNCE_NUM 2 /* (number of announcement packets) */
|
|
||||||
#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */
|
|
||||||
#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */
|
|
||||||
#define MAX_CONFLICTS LWIP_AUTOIP_MAX_CONFLICTS /* (max conflicts before rate limiting) */
|
|
||||||
#define RATE_LIMIT_INTERVAL LWIP_AUTOIP_RATE_LIMIT_INTERVAL /* seconds (delay between successive attempts) */
|
|
||||||
#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */
|
|
||||||
|
|
||||||
/* AutoIP client states */
|
|
||||||
#define AUTOIP_STATE_OFF 0
|
|
||||||
#define AUTOIP_STATE_PROBING 1
|
|
||||||
#define AUTOIP_STATE_ANNOUNCING 2
|
|
||||||
#define AUTOIP_STATE_BOUND 3
|
|
||||||
|
|
||||||
struct autoip
|
|
||||||
{
|
|
||||||
ip4_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */
|
|
||||||
u8_t state; /* current AutoIP state machine state */
|
|
||||||
u8_t sent_num; /* sent number of probes or announces, dependent on state */
|
|
||||||
u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */
|
|
||||||
u8_t lastconflict; /* ticks until a conflict can be solved by defending */
|
|
||||||
u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define autoip_init() /* Compatibility define, no init needed. */
|
|
||||||
|
|
||||||
/** Set a struct autoip allocated by the application to work with */
|
|
||||||
void autoip_set_struct(struct netif *netif, struct autoip *autoip);
|
|
||||||
|
|
||||||
/** Remove a struct autoip previously set to the netif using autoip_set_struct() */
|
|
||||||
#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0)
|
|
||||||
|
|
||||||
/** Start AutoIP client */
|
|
||||||
err_t autoip_start(struct netif *netif);
|
|
||||||
|
|
||||||
/** Stop AutoIP client */
|
|
||||||
err_t autoip_stop(struct netif *netif);
|
|
||||||
|
|
||||||
/** Handles every incoming ARP Packet, called by etharp_arp_input */
|
|
||||||
void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr);
|
|
||||||
|
|
||||||
/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */
|
|
||||||
void autoip_tmr(void);
|
|
||||||
|
|
||||||
/** Handle a possible change in the network configuration */
|
|
||||||
void autoip_network_changed(struct netif *netif);
|
|
||||||
|
|
||||||
/** check if AutoIP supplied netif->ip_addr */
|
|
||||||
u8_t autoip_supplied_address(struct netif *netif);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_AUTOIP */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_AUTOIP_H */
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_DEBUG_H
|
|
||||||
#define LWIP_HDR_DEBUG_H
|
|
||||||
|
|
||||||
#include "lwip/arch.h"
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
/** lower two bits indicate debug level
|
|
||||||
* - 0 all
|
|
||||||
* - 1 warning
|
|
||||||
* - 2 serious
|
|
||||||
* - 3 severe
|
|
||||||
*/
|
|
||||||
#define LWIP_DBG_LEVEL_ALL 0x00
|
|
||||||
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */
|
|
||||||
#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
|
|
||||||
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
|
|
||||||
#define LWIP_DBG_LEVEL_SEVERE 0x03
|
|
||||||
#define LWIP_DBG_MASK_LEVEL 0x03
|
|
||||||
|
|
||||||
/** flag for LWIP_DEBUGF to enable that debug message */
|
|
||||||
#define LWIP_DBG_ON 0x80U
|
|
||||||
/** flag for LWIP_DEBUGF to disable that debug message */
|
|
||||||
#define LWIP_DBG_OFF 0x00U
|
|
||||||
|
|
||||||
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
|
|
||||||
#define LWIP_DBG_TRACE 0x40U
|
|
||||||
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
|
|
||||||
#define LWIP_DBG_STATE 0x20U
|
|
||||||
/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */
|
|
||||||
#define LWIP_DBG_FRESH 0x10U
|
|
||||||
/** flag for LWIP_DEBUGF to halt after printing this debug message */
|
|
||||||
#define LWIP_DBG_HALT 0x08U
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LWIP_NOASSERT: Disable LWIP_ASSERT checks.
|
|
||||||
* -- To disable assertions define LWIP_NOASSERT in arch/cc.h.
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_NOASSERT
|
|
||||||
#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
|
|
||||||
LWIP_PLATFORM_ASSERT(message); } while(0)
|
|
||||||
#ifndef LWIP_PLATFORM_ASSERT
|
|
||||||
#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h"
|
|
||||||
#endif
|
|
||||||
#else /* LWIP_NOASSERT */
|
|
||||||
#define LWIP_ASSERT(message, assertion)
|
|
||||||
#endif /* LWIP_NOASSERT */
|
|
||||||
|
|
||||||
/** if "expression" isn't true, then print "message" and execute "handler" expression */
|
|
||||||
#ifndef LWIP_ERROR
|
|
||||||
#ifndef LWIP_NOASSERT
|
|
||||||
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
|
|
||||||
#elif defined LWIP_DEBUG
|
|
||||||
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message))
|
|
||||||
#else
|
|
||||||
#define LWIP_PLATFORM_ERROR(message)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
|
|
||||||
LWIP_PLATFORM_ERROR(message); handler;}} while(0)
|
|
||||||
#endif /* LWIP_ERROR */
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
#ifndef LWIP_PLATFORM_DIAG
|
|
||||||
#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h"
|
|
||||||
#endif
|
|
||||||
/** print debug message only if debug message type is enabled...
|
|
||||||
* AND is of correct type AND is at least LWIP_DBG_LEVEL
|
|
||||||
*/
|
|
||||||
#define LWIP_DEBUGF(debug, message) do { \
|
|
||||||
if ( \
|
|
||||||
((debug) & LWIP_DBG_ON) && \
|
|
||||||
((debug) & LWIP_DBG_TYPES_ON) && \
|
|
||||||
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
|
|
||||||
LWIP_PLATFORM_DIAG(message); \
|
|
||||||
if ((debug) & LWIP_DBG_HALT) { \
|
|
||||||
while(1); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#else /* LWIP_DEBUG */
|
|
||||||
#define LWIP_DEBUGF(debug, message)
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_DEBUG_H */
|
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_DEF_H
|
|
||||||
#define LWIP_HDR_DEF_H
|
|
||||||
|
|
||||||
/* arch.h might define NULL already */
|
|
||||||
#include "lwip/arch.h"
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#if LWIP_PERF
|
|
||||||
#include "arch/perf.h"
|
|
||||||
#else /* LWIP_PERF */
|
|
||||||
#define PERF_START /* null definition */
|
|
||||||
#define PERF_STOP(x) /* null definition */
|
|
||||||
#endif /* LWIP_PERF */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y))
|
|
||||||
#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y))
|
|
||||||
|
|
||||||
/* Get the number of entries in an array ('x' must NOT be a pointer!) */
|
|
||||||
#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
|
|
||||||
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL ((void *)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Endianess-optimized shifting of two u8_t to create one u16_t */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
#define LWIP_MAKE_U16(a, b) ((a << 8) | b)
|
|
||||||
#else
|
|
||||||
#define LWIP_MAKE_U16(a, b) ((b << 8) | a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_PLATFORM_BYTESWAP
|
|
||||||
#define LWIP_PLATFORM_BYTESWAP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_PREFIX_BYTEORDER_FUNCS
|
|
||||||
/* workaround for naming collisions on some platforms */
|
|
||||||
|
|
||||||
#ifdef htons
|
|
||||||
#undef htons
|
|
||||||
#endif /* htons */
|
|
||||||
#ifdef htonl
|
|
||||||
#undef htonl
|
|
||||||
#endif /* htonl */
|
|
||||||
#ifdef ntohs
|
|
||||||
#undef ntohs
|
|
||||||
#endif /* ntohs */
|
|
||||||
#ifdef ntohl
|
|
||||||
#undef ntohl
|
|
||||||
#endif /* ntohl */
|
|
||||||
|
|
||||||
#define htons(x) lwip_htons(x)
|
|
||||||
#define ntohs(x) lwip_ntohs(x)
|
|
||||||
#define htonl(x) lwip_htonl(x)
|
|
||||||
#define ntohl(x) lwip_ntohl(x)
|
|
||||||
#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
#define lwip_htons(x) (x)
|
|
||||||
#define lwip_ntohs(x) (x)
|
|
||||||
#define lwip_htonl(x) (x)
|
|
||||||
#define lwip_ntohl(x) (x)
|
|
||||||
#define PP_HTONS(x) (x)
|
|
||||||
#define PP_NTOHS(x) (x)
|
|
||||||
#define PP_HTONL(x) (x)
|
|
||||||
#define PP_NTOHL(x) (x)
|
|
||||||
#else /* BYTE_ORDER != BIG_ENDIAN */
|
|
||||||
#if LWIP_PLATFORM_BYTESWAP
|
|
||||||
#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
|
|
||||||
#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
|
|
||||||
#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
|
|
||||||
#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
|
|
||||||
#else /* LWIP_PLATFORM_BYTESWAP */
|
|
||||||
u16_t lwip_htons(u16_t x);
|
|
||||||
u16_t lwip_ntohs(u16_t x);
|
|
||||||
u32_t lwip_htonl(u32_t x);
|
|
||||||
u32_t lwip_ntohl(u32_t x);
|
|
||||||
#endif /* LWIP_PLATFORM_BYTESWAP */
|
|
||||||
|
|
||||||
/* These macros should be calculated by the preprocessor and are used
|
|
||||||
with compile-time constants only (so that there is no little-endian
|
|
||||||
overhead at runtime). */
|
|
||||||
#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
|
|
||||||
#define PP_NTOHS(x) PP_HTONS(x)
|
|
||||||
#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
|
|
||||||
(((x) & 0xff00) << 8) | \
|
|
||||||
(((x) & 0xff0000UL) >> 8) | \
|
|
||||||
(((x) & 0xff000000UL) >> 24))
|
|
||||||
#define PP_NTOHL(x) PP_HTONL(x)
|
|
||||||
|
|
||||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_DEF_H */
|
|
||||||
|
|
|
@ -1,314 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
|
|
||||||
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
|
|
||||||
* 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: Leon Woestenberg <leon.woestenberg@gmx.net>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_DHCP_H
|
|
||||||
#define LWIP_HDR_DHCP_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/udp.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
|
|
||||||
#define DHCP_COARSE_TIMER_SECS 1
|
|
||||||
/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
|
|
||||||
#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
|
|
||||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
|
||||||
#define DHCP_FINE_TIMER_MSECS 500
|
|
||||||
|
|
||||||
#define DHCP_CHADDR_LEN 16U
|
|
||||||
#define DHCP_SNAME_LEN 64U
|
|
||||||
#define DHCP_FILE_LEN 128U
|
|
||||||
|
|
||||||
struct dhcp
|
|
||||||
{
|
|
||||||
/** transaction identifier of last sent request */
|
|
||||||
u32_t xid;
|
|
||||||
/** incoming msg */
|
|
||||||
struct dhcp_msg *msg_in;
|
|
||||||
/** track PCB allocation state */
|
|
||||||
u8_t pcb_allocated;
|
|
||||||
/** current DHCP state machine state */
|
|
||||||
u8_t state;
|
|
||||||
/** retries of current request */
|
|
||||||
u8_t tries;
|
|
||||||
#if LWIP_DHCP_AUTOIP_COOP
|
|
||||||
u8_t autoip_coop_state;
|
|
||||||
#endif
|
|
||||||
u8_t subnet_mask_given;
|
|
||||||
|
|
||||||
struct pbuf *p_out; /* pbuf of outcoming msg */
|
|
||||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
|
||||||
u16_t options_out_len; /* outgoing msg options length */
|
|
||||||
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
|
|
||||||
u32_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
|
||||||
u32_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
|
||||||
u32_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */
|
|
||||||
u32_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */
|
|
||||||
u32_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
|
|
||||||
u32_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
|
|
||||||
ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */
|
|
||||||
ip4_addr_t offered_ip_addr;
|
|
||||||
ip4_addr_t offered_sn_mask;
|
|
||||||
ip4_addr_t offered_gw_addr;
|
|
||||||
|
|
||||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
|
||||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
|
||||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */
|
|
||||||
#if LWIP_DHCP_BOOTP_FILE
|
|
||||||
ip_addr_t offered_si_addr;
|
|
||||||
char boot_file_name[DHCP_FILE_LEN];
|
|
||||||
#endif /* LWIP_DHCP_BOOTPFILE */
|
|
||||||
|
|
||||||
/* Espressif add start. */
|
|
||||||
#ifdef ESP_LWIP
|
|
||||||
void (*cb)(struct netif*); /* callback for dhcp, add a parameter to show dhcp status if needed */
|
|
||||||
#else
|
|
||||||
void (*cb)(void); /* callback for dhcp, add a parameter to show dhcp status if needed */
|
|
||||||
#endif
|
|
||||||
/* Espressif add end. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* MUST be compiled with "pack structs" or equivalent! */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
/** minimum set of fields of any DHCP message */
|
|
||||||
struct dhcp_msg
|
|
||||||
{
|
|
||||||
PACK_STRUCT_FLD_8(u8_t op);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t htype);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t hlen);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t hops);
|
|
||||||
PACK_STRUCT_FIELD(u32_t xid);
|
|
||||||
PACK_STRUCT_FIELD(u16_t secs);
|
|
||||||
PACK_STRUCT_FIELD(u16_t flags);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]);
|
|
||||||
PACK_STRUCT_FIELD(u32_t cookie);
|
|
||||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
|
||||||
/** make sure user does not configure this too small */
|
|
||||||
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
|
||||||
# undef DHCP_OPTIONS_LEN
|
|
||||||
#endif
|
|
||||||
/** allow this to be configured in lwipopts.h, but not too small */
|
|
||||||
#if (!defined(DHCP_OPTIONS_LEN))
|
|
||||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
|
||||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
|
||||||
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
|
||||||
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
|
||||||
void dhcp_cleanup(struct netif *netif);
|
|
||||||
/* Espressif add start. */
|
|
||||||
/** set callback for DHCP */
|
|
||||||
#ifdef ESP_LWIP
|
|
||||||
void dhcp_set_cb(struct netif *netif, void (*cb)(struct netif*));
|
|
||||||
#else
|
|
||||||
void dhcp_set_cb(struct netif *netif, void (*cb)(void));
|
|
||||||
#endif
|
|
||||||
/* Espressif add end. */
|
|
||||||
/** start DHCP configuration */
|
|
||||||
err_t dhcp_start(struct netif *netif);
|
|
||||||
/** enforce early lease renewal (not needed normally)*/
|
|
||||||
err_t dhcp_renew(struct netif *netif);
|
|
||||||
/** release the DHCP lease, usually called before dhcp_stop()*/
|
|
||||||
err_t dhcp_release(struct netif *netif);
|
|
||||||
/** stop DHCP configuration */
|
|
||||||
void dhcp_stop(struct netif *netif);
|
|
||||||
/** inform server of our manual IP address */
|
|
||||||
void dhcp_inform(struct netif *netif);
|
|
||||||
/** Handle a possible change in the network configuration */
|
|
||||||
void dhcp_network_changed(struct netif *netif);
|
|
||||||
|
|
||||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
|
||||||
#if DHCP_DOES_ARP_CHECK
|
|
||||||
void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** check if DHCP supplied netif->ip_addr */
|
|
||||||
u8_t dhcp_supplied_address(struct netif *netif);
|
|
||||||
|
|
||||||
/** to be called every minute */
|
|
||||||
void dhcp_coarse_tmr(void);
|
|
||||||
/** to be called every half second */
|
|
||||||
void dhcp_fine_tmr(void);
|
|
||||||
|
|
||||||
/** DHCP message item offsets and length */
|
|
||||||
#define DHCP_OP_OFS 0
|
|
||||||
#define DHCP_HTYPE_OFS 1
|
|
||||||
#define DHCP_HLEN_OFS 2
|
|
||||||
#define DHCP_HOPS_OFS 3
|
|
||||||
#define DHCP_XID_OFS 4
|
|
||||||
#define DHCP_SECS_OFS 8
|
|
||||||
#define DHCP_FLAGS_OFS 10
|
|
||||||
#define DHCP_CIADDR_OFS 12
|
|
||||||
#define DHCP_YIADDR_OFS 16
|
|
||||||
#define DHCP_SIADDR_OFS 20
|
|
||||||
#define DHCP_GIADDR_OFS 24
|
|
||||||
#define DHCP_CHADDR_OFS 28
|
|
||||||
#define DHCP_SNAME_OFS 44
|
|
||||||
#define DHCP_FILE_OFS 108
|
|
||||||
#define DHCP_MSG_LEN 236
|
|
||||||
|
|
||||||
#define DHCP_COOKIE_OFS DHCP_MSG_LEN
|
|
||||||
#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4)
|
|
||||||
|
|
||||||
#define DHCP_CLIENT_PORT 68
|
|
||||||
#define DHCP_SERVER_PORT 67
|
|
||||||
|
|
||||||
/** DHCP client states */
|
|
||||||
#define DHCP_STATE_OFF 0
|
|
||||||
#define DHCP_STATE_REQUESTING 1
|
|
||||||
#define DHCP_STATE_INIT 2
|
|
||||||
#define DHCP_STATE_REBOOTING 3
|
|
||||||
#define DHCP_STATE_REBINDING 4
|
|
||||||
#define DHCP_STATE_RENEWING 5
|
|
||||||
#define DHCP_STATE_SELECTING 6
|
|
||||||
#define DHCP_STATE_INFORMING 7
|
|
||||||
#define DHCP_STATE_CHECKING 8
|
|
||||||
/** not yet implemented #define DHCP_STATE_PERMANENT 9 */
|
|
||||||
#define DHCP_STATE_BOUND 10
|
|
||||||
/** not yet implemented #define DHCP_STATE_RELEASING 11 */
|
|
||||||
#define DHCP_STATE_BACKING_OFF 12
|
|
||||||
|
|
||||||
/** AUTOIP cooperation flags */
|
|
||||||
#define DHCP_AUTOIP_COOP_STATE_OFF 0
|
|
||||||
#define DHCP_AUTOIP_COOP_STATE_ON 1
|
|
||||||
|
|
||||||
#define DHCP_BOOTREQUEST 1
|
|
||||||
#define DHCP_BOOTREPLY 2
|
|
||||||
|
|
||||||
/** DHCP message types */
|
|
||||||
#define DHCP_DISCOVER 1
|
|
||||||
#define DHCP_OFFER 2
|
|
||||||
#define DHCP_REQUEST 3
|
|
||||||
#define DHCP_DECLINE 4
|
|
||||||
#define DHCP_ACK 5
|
|
||||||
#define DHCP_NAK 6
|
|
||||||
#define DHCP_RELEASE 7
|
|
||||||
#define DHCP_INFORM 8
|
|
||||||
|
|
||||||
/** DHCP hardware type, currently only ethernet is supported */
|
|
||||||
#define DHCP_HTYPE_ETH 1
|
|
||||||
|
|
||||||
#define DHCP_MAGIC_COOKIE 0x63825363UL
|
|
||||||
|
|
||||||
/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */
|
|
||||||
|
|
||||||
/** BootP options */
|
|
||||||
#define DHCP_OPTION_PAD 0
|
|
||||||
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
|
||||||
#define DHCP_OPTION_ROUTER 3
|
|
||||||
#define DHCP_OPTION_DNS_SERVER 6
|
|
||||||
#define DHCP_OPTION_HOSTNAME 12
|
|
||||||
#define DHCP_OPTION_IP_TTL 23
|
|
||||||
#define DHCP_OPTION_MTU 26
|
|
||||||
#define DHCP_OPTION_BROADCAST 28
|
|
||||||
#define DHCP_OPTION_TCP_TTL 37
|
|
||||||
#define DHCP_OPTION_NTP 42
|
|
||||||
#define DHCP_OPTION_END 255
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
/**add options for support more router by liuHan**/
|
|
||||||
#define DHCP_OPTION_DOMAIN_NAME 15
|
|
||||||
#define DHCP_OPTION_PRD 31
|
|
||||||
#define DHCP_OPTION_STATIC_ROUTER 33
|
|
||||||
#define DHCP_OPTION_VSN 43
|
|
||||||
#define DHCP_OPTION_NB_TINS 44
|
|
||||||
#define DHCP_OPTION_NB_TINT 46
|
|
||||||
#define DHCP_OPTION_NB_TIS 47
|
|
||||||
#define DHCP_OPTION_CLASSLESS_STATIC_ROUTER 121
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** DHCP options */
|
|
||||||
#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */
|
|
||||||
#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */
|
|
||||||
#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */
|
|
||||||
|
|
||||||
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
|
|
||||||
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
|
|
||||||
|
|
||||||
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
|
|
||||||
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
|
|
||||||
|
|
||||||
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
|
|
||||||
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
|
|
||||||
|
|
||||||
#define DHCP_OPTION_T1 58 /* T1 renewal time */
|
|
||||||
#define DHCP_OPTION_T2 59 /* T2 rebinding time */
|
|
||||||
#define DHCP_OPTION_US 60
|
|
||||||
#define DHCP_OPTION_CLIENT_ID 61
|
|
||||||
#define DHCP_OPTION_TFTP_SERVERNAME 66
|
|
||||||
#define DHCP_OPTION_BOOTFILE 67
|
|
||||||
|
|
||||||
/** possible combinations of overloading the file and sname fields with options */
|
|
||||||
#define DHCP_OVERLOAD_NONE 0
|
|
||||||
#define DHCP_OVERLOAD_FILE 1
|
|
||||||
#define DHCP_OVERLOAD_SNAME 2
|
|
||||||
#define DHCP_OVERLOAD_SNAME_FILE 3
|
|
||||||
|
|
||||||
#if LWIP_DHCP_GET_NTP_SRV
|
|
||||||
/** This function must exist, in other to add offered NTP servers to
|
|
||||||
* the NTP (or SNTP) engine.
|
|
||||||
* See LWIP_DHCP_MAX_NTP_SERVERS */
|
|
||||||
extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
|
|
||||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_DHCP */
|
|
||||||
|
|
||||||
#endif /*LWIP_HDR_DHCP_H*/
|
|
|
@ -1,58 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 address autoconfiguration as per RFC 4862.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
* IPv6 address autoconfiguration as per RFC 4862.
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_IP6_DHCP6_H
|
|
||||||
#define LWIP_HDR_IP6_DHCP6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
|
|
||||||
struct dhcp6
|
|
||||||
{
|
|
||||||
/*TODO: implement DHCP6*/
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6_DHCP6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP6_DHCP6_H */
|
|
|
@ -1,119 +0,0 @@
|
||||||
/**
|
|
||||||
* lwip DNS resolver header file.
|
|
||||||
|
|
||||||
* Author: Jim Pettinato
|
|
||||||
* April 2007
|
|
||||||
|
|
||||||
* ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_DNS_H
|
|
||||||
#define LWIP_HDR_DNS_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if ESP_DNS
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_DNS
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** DNS timer period */
|
|
||||||
#define DNS_TMR_INTERVAL 1000
|
|
||||||
|
|
||||||
/* DNS resolve types: */
|
|
||||||
#define LWIP_DNS_ADDRTYPE_IPV4 0
|
|
||||||
#define LWIP_DNS_ADDRTYPE_IPV6 1
|
|
||||||
#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */
|
|
||||||
#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
#ifndef LWIP_DNS_ADDRTYPE_DEFAULT
|
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6
|
|
||||||
#endif
|
|
||||||
#elif defined(LWIP_IPV4)
|
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4
|
|
||||||
#else
|
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DNS_LOCAL_HOSTLIST
|
|
||||||
/** struct used for local host-list */
|
|
||||||
struct local_hostlist_entry {
|
|
||||||
/** static hostname */
|
|
||||||
const char *name;
|
|
||||||
/** static host address in network byteorder */
|
|
||||||
ip_addr_t addr;
|
|
||||||
struct local_hostlist_entry *next;
|
|
||||||
};
|
|
||||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
|
||||||
#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
|
|
||||||
#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
|
|
||||||
#endif
|
|
||||||
#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
|
|
||||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
|
||||||
#endif /* DNS_LOCAL_HOSTLIST */
|
|
||||||
|
|
||||||
/** Callback which is invoked when a hostname is found.
|
|
||||||
* A function of this type must be implemented by the application using the DNS resolver.
|
|
||||||
* @param name pointer to the name that was looked up.
|
|
||||||
* @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
|
|
||||||
* or NULL if the name could not be found (or on any other error).
|
|
||||||
* @param callback_arg a user-specified callback argument passed to dns_gethostbyname
|
|
||||||
*/
|
|
||||||
typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
|
|
||||||
|
|
||||||
void dns_init(void);
|
|
||||||
void dns_tmr(void);
|
|
||||||
void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver);
|
|
||||||
void dns_clear_servers(bool keep_fallback);
|
|
||||||
ip_addr_t dns_getserver(u8_t numdns);
|
|
||||||
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
|
|
||||||
dns_found_callback found, void *callback_arg);
|
|
||||||
err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr,
|
|
||||||
dns_found_callback found, void *callback_arg,
|
|
||||||
u8_t dns_addrtype);
|
|
||||||
|
|
||||||
|
|
||||||
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
|
||||||
int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
|
|
||||||
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
|
|
||||||
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_DNS_H */
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_ERR_H
|
|
||||||
#define LWIP_HDR_ERR_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/arch.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Define LWIP_ERR_T in cc.h if you want to use
|
|
||||||
* a different type for your platform (must be signed). */
|
|
||||||
#ifdef LWIP_ERR_T
|
|
||||||
typedef LWIP_ERR_T err_t;
|
|
||||||
#else /* LWIP_ERR_T */
|
|
||||||
typedef s8_t err_t;
|
|
||||||
#endif /* LWIP_ERR_T*/
|
|
||||||
|
|
||||||
/* Definitions for error constants. */
|
|
||||||
|
|
||||||
#define ERR_OK 0 /* No error, everything OK. */
|
|
||||||
#define ERR_MEM -1 /* Out of memory error. */
|
|
||||||
#define ERR_BUF -2 /* Buffer error. */
|
|
||||||
#define ERR_TIMEOUT -3 /* Timeout. */
|
|
||||||
#define ERR_RTE -4 /* Routing problem. */
|
|
||||||
#define ERR_INPROGRESS -5 /* Operation in progress */
|
|
||||||
#define ERR_VAL -6 /* Illegal value. */
|
|
||||||
#define ERR_WOULDBLOCK -7 /* Operation would block. */
|
|
||||||
#define ERR_USE -8 /* Address in use. */
|
|
||||||
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
#define ERR_ALREADY -9 /* Already connected. */
|
|
||||||
#define ERR_ISCONN -10 /* Conn already established.*/
|
|
||||||
#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN)
|
|
||||||
#define ERR_ABRT -11 /* Connection aborted. */
|
|
||||||
#define ERR_RST -12 /* Connection reset. */
|
|
||||||
#define ERR_CLSD -13 /* Connection closed. */
|
|
||||||
#define ERR_CONN -14 /* Not connected. */
|
|
||||||
#define ERR_ARG -15 /* Illegal argument. */
|
|
||||||
#define ERR_IF -16 /* Low-level netif error */
|
|
||||||
#else
|
|
||||||
#define ERR_ALREADY -9 /* Already connecting. */
|
|
||||||
#define ERR_ISCONN -10 /* Conn already established.*/
|
|
||||||
#define ERR_CONN -11 /* Not connected. */
|
|
||||||
#define ERR_IF -12 /* Low-level netif error */
|
|
||||||
#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT)
|
|
||||||
#define ERR_ABRT -13 /* Connection aborted. */
|
|
||||||
#define ERR_RST -14 /* Connection reset. */
|
|
||||||
#define ERR_CLSD -15 /* Connection closed. */
|
|
||||||
#define ERR_ARG -16 /* Illegal argument. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
extern const char *lwip_strerr(err_t err);
|
|
||||||
#else
|
|
||||||
#define lwip_strerr(x) ""
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ERR_H */
|
|
|
@ -1,68 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_ETHIP6_H
|
|
||||||
#define LWIP_HDR_ETHIP6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ETHIP6_H */
|
|
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_ICMP_H
|
|
||||||
#define LWIP_HDR_ICMP_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_ICMP6
|
|
||||||
#include "lwip/icmp6.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ICMP_ER 0 /* echo reply */
|
|
||||||
#define ICMP_DUR 3 /* destination unreachable */
|
|
||||||
#define ICMP_SQ 4 /* source quench */
|
|
||||||
#define ICMP_RD 5 /* redirect */
|
|
||||||
#define ICMP_ECHO 8 /* echo */
|
|
||||||
#define ICMP_TE 11 /* time exceeded */
|
|
||||||
#define ICMP_PP 12 /* parameter problem */
|
|
||||||
#define ICMP_TS 13 /* timestamp */
|
|
||||||
#define ICMP_TSR 14 /* timestamp reply */
|
|
||||||
#define ICMP_IRQ 15 /* information request */
|
|
||||||
#define ICMP_IR 16 /* information reply */
|
|
||||||
#define ICMP_AM 17 /* address mask request */
|
|
||||||
#define ICMP_AMR 18 /* address mask reply */
|
|
||||||
|
|
||||||
enum icmp_dur_type {
|
|
||||||
ICMP_DUR_NET = 0, /* net unreachable */
|
|
||||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
|
||||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
|
||||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
|
||||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
|
||||||
ICMP_DUR_SR = 5 /* source route failed */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum icmp_te_type {
|
|
||||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
|
||||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
/** This is the standard ICMP header only that the u32_t data
|
|
||||||
* is split to two u16_t like ICMP echo needs it.
|
|
||||||
* This header is also used for other ICMP types that do not
|
|
||||||
* use the data part.
|
|
||||||
*/
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct icmp_echo_hdr {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u16_t id);
|
|
||||||
PACK_STRUCT_FIELD(u16_t seqno);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ICMPH_TYPE(hdr) ((hdr)->type)
|
|
||||||
#define ICMPH_CODE(hdr) ((hdr)->code)
|
|
||||||
|
|
||||||
/** Combines type and code to an u16_t */
|
|
||||||
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
|
|
||||||
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
|
||||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
|
||||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_ICMP */
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
#if LWIP_ICMP && LWIP_ICMP6
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \
|
|
||||||
icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \
|
|
||||||
icmp_dest_unreach(pbuf, ICMP_DUR_PORT))
|
|
||||||
#elif LWIP_ICMP
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0)
|
|
||||||
#elif LWIP_ICMP6
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0)
|
|
||||||
#else
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf)
|
|
||||||
#endif
|
|
||||||
#elif LWIP_IPV6 && LWIP_ICMP6
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT)
|
|
||||||
#elif LWIP_IPV4 && LWIP_ICMP
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT)
|
|
||||||
#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */
|
|
||||||
#define icmp_port_unreach(isipv6, pbuf)
|
|
||||||
#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ICMP_H */
|
|
|
@ -1,152 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 version of ICMP, as per RFC 4443.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_ICMP6_H
|
|
||||||
#define LWIP_HDR_ICMP6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum icmp6_type {
|
|
||||||
ICMP6_TYPE_DUR = 1, /* Destination unreachable */
|
|
||||||
ICMP6_TYPE_PTB = 2, /* Packet too big */
|
|
||||||
ICMP6_TYPE_TE = 3, /* Time exceeded */
|
|
||||||
ICMP6_TYPE_PP = 4, /* Parameter problem */
|
|
||||||
ICMP6_TYPE_PE1 = 100, /* Private experimentation */
|
|
||||||
ICMP6_TYPE_PE2 = 101, /* Private experimentation */
|
|
||||||
ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */
|
|
||||||
|
|
||||||
ICMP6_TYPE_EREQ = 128, /* Echo request */
|
|
||||||
ICMP6_TYPE_EREP = 129, /* Echo reply */
|
|
||||||
ICMP6_TYPE_MLQ = 130, /* Multicast listener query */
|
|
||||||
ICMP6_TYPE_MLR = 131, /* Multicast listener report */
|
|
||||||
ICMP6_TYPE_MLD = 132, /* Multicast listener done */
|
|
||||||
ICMP6_TYPE_RS = 133, /* Router solicitation */
|
|
||||||
ICMP6_TYPE_RA = 134, /* Router advertisement */
|
|
||||||
ICMP6_TYPE_NS = 135, /* Neighbor solicitation */
|
|
||||||
ICMP6_TYPE_NA = 136, /* Neighbor advertisement */
|
|
||||||
ICMP6_TYPE_RD = 137, /* Redirect */
|
|
||||||
ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */
|
|
||||||
ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */
|
|
||||||
ICMP6_TYPE_MRT = 153, /* Multicast router termination */
|
|
||||||
ICMP6_TYPE_PE3 = 200, /* Private experimentation */
|
|
||||||
ICMP6_TYPE_PE4 = 201, /* Private experimentation */
|
|
||||||
ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum icmp6_dur_code {
|
|
||||||
ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */
|
|
||||||
ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */
|
|
||||||
ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */
|
|
||||||
ICMP6_DUR_ADDRESS = 3, /* Address unreachable */
|
|
||||||
ICMP6_DUR_PORT = 4, /* Port unreachable */
|
|
||||||
ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */
|
|
||||||
ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum icmp6_te_code {
|
|
||||||
ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */
|
|
||||||
ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum icmp6_pp_code {
|
|
||||||
ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */
|
|
||||||
ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */
|
|
||||||
ICMP6_PP_OPTION = 2 /* Unrecognized IPv6 option encountered */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** This is the standard ICMP6 header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct icmp6_hdr {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t data);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** This is the ICMP6 header adapted for echo req/resp. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct icmp6_echo_hdr {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u16_t id);
|
|
||||||
PACK_STRUCT_FIELD(u16_t seqno);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
void icmp6_input(struct pbuf *p, struct netif *inp);
|
|
||||||
void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c);
|
|
||||||
void icmp6_packet_too_big(struct pbuf *p, u32_t mtu);
|
|
||||||
void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c);
|
|
||||||
void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer);
|
|
||||||
|
|
||||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ICMP6_H */
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_IGMP_H
|
|
||||||
#define LWIP_HDR_IGMP_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* IGMP timer */
|
|
||||||
#define IGMP_TMR_INTERVAL 100 /* Milliseconds */
|
|
||||||
#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL)
|
|
||||||
#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL)
|
|
||||||
|
|
||||||
/* MAC Filter Actions, these are passed to a netif's
|
|
||||||
* igmp_mac_filter callback function. */
|
|
||||||
#define IGMP_DEL_MAC_FILTER 0
|
|
||||||
#define IGMP_ADD_MAC_FILTER 1
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* igmp group structure - there is
|
|
||||||
* a list of groups for each interface
|
|
||||||
* these should really be linked from the interface, but
|
|
||||||
* if we keep them separate we will not affect the lwip original code
|
|
||||||
* too much
|
|
||||||
*
|
|
||||||
* There will be a group for the all systems group address but this
|
|
||||||
* will not run the state machine as it is used to kick off reports
|
|
||||||
* from all the other groups
|
|
||||||
*/
|
|
||||||
struct igmp_group {
|
|
||||||
/** next link */
|
|
||||||
struct igmp_group *next;
|
|
||||||
/** interface on which the group is active */
|
|
||||||
struct netif *netif;
|
|
||||||
/** multicast address */
|
|
||||||
ip4_addr_t group_address;
|
|
||||||
/** signifies we were the last person to report */
|
|
||||||
u8_t last_reporter_flag;
|
|
||||||
/** current state of the group */
|
|
||||||
u8_t group_state;
|
|
||||||
/** timer for reporting, negative is OFF */
|
|
||||||
u16_t timer;
|
|
||||||
/** counter of simultaneous uses */
|
|
||||||
u8_t use;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Prototypes */
|
|
||||||
void igmp_init(void);
|
|
||||||
err_t igmp_start(struct netif *netif);
|
|
||||||
err_t igmp_stop(struct netif *netif);
|
|
||||||
void igmp_report_groups(struct netif *netif);
|
|
||||||
struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr);
|
|
||||||
void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest);
|
|
||||||
err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr);
|
|
||||||
err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr);
|
|
||||||
err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr);
|
|
||||||
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr);
|
|
||||||
void igmp_tmr(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IGMP */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IGMP_H */
|
|
|
@ -1,172 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* This file (together with sockets.h) aims to provide structs and functions from
|
|
||||||
* - arpa/inet.h
|
|
||||||
* - netinet/in.h
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_INET_H
|
|
||||||
#define LWIP_HDR_INET_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED
|
|
||||||
to prevent this code from redefining it. */
|
|
||||||
#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED)
|
|
||||||
typedef u32_t in_addr_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct in_addr {
|
|
||||||
in_addr_t s_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct in6_addr {
|
|
||||||
union {
|
|
||||||
u32_t u32_addr[4];
|
|
||||||
u8_t u8_addr[16];
|
|
||||||
} un;
|
|
||||||
#define s6_addr un.u8_addr
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 255.255.255.255 */
|
|
||||||
#define INADDR_NONE IPADDR_NONE
|
|
||||||
/** 127.0.0.1 */
|
|
||||||
#define INADDR_LOOPBACK IPADDR_LOOPBACK
|
|
||||||
/** 0.0.0.0 */
|
|
||||||
#define INADDR_ANY IPADDR_ANY
|
|
||||||
/** 255.255.255.255 */
|
|
||||||
#define INADDR_BROADCAST IPADDR_BROADCAST
|
|
||||||
|
|
||||||
/** This macro can be used to initialize a variable of type struct in6_addr
|
|
||||||
to the IPv6 wildcard address. */
|
|
||||||
#define IN6ADDR_ANY_INIT {{{0,0,0,0}}}
|
|
||||||
/** This macro can be used to initialize a variable of type struct in6_addr
|
|
||||||
to the IPv6 loopback address. */
|
|
||||||
#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}}
|
|
||||||
/** This variable is initialized by the system to contain the wildcard IPv6 address. */
|
|
||||||
extern const struct in6_addr in6addr_any;
|
|
||||||
|
|
||||||
/* Definitions of the bits in an (IPv4) Internet address integer.
|
|
||||||
|
|
||||||
On subnets, host and network parts are found according to
|
|
||||||
the subnet mask, not these masks. */
|
|
||||||
#define IN_CLASSA(a) IP_CLASSA(a)
|
|
||||||
#define IN_CLASSA_NET IP_CLASSA_NET
|
|
||||||
#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT
|
|
||||||
#define IN_CLASSA_HOST IP_CLASSA_HOST
|
|
||||||
#define IN_CLASSA_MAX IP_CLASSA_MAX
|
|
||||||
|
|
||||||
#define IN_CLASSB(b) IP_CLASSB(b)
|
|
||||||
#define IN_CLASSB_NET IP_CLASSB_NET
|
|
||||||
#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT
|
|
||||||
#define IN_CLASSB_HOST IP_CLASSB_HOST
|
|
||||||
#define IN_CLASSB_MAX IP_CLASSB_MAX
|
|
||||||
|
|
||||||
#define IN_CLASSC(c) IP_CLASSC(c)
|
|
||||||
#define IN_CLASSC_NET IP_CLASSC_NET
|
|
||||||
#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT
|
|
||||||
#define IN_CLASSC_HOST IP_CLASSC_HOST
|
|
||||||
#define IN_CLASSC_MAX IP_CLASSC_MAX
|
|
||||||
|
|
||||||
#define IN_CLASSD(d) IP_CLASSD(d)
|
|
||||||
#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */
|
|
||||||
#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */
|
|
||||||
#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */
|
|
||||||
#define IN_CLASSD_MAX IP_CLASSD_MAX
|
|
||||||
|
|
||||||
#define IN_MULTICAST(a) IP_MULTICAST(a)
|
|
||||||
|
|
||||||
#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a)
|
|
||||||
#define IN_BADCLASS(a) IP_BADCLASS(a)
|
|
||||||
|
|
||||||
#define IN_LOOPBACKNET IP_LOOPBACKNET
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef INET_ADDRSTRLEN
|
|
||||||
#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX
|
|
||||||
#endif
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#ifndef INET6_ADDRSTRLEN
|
|
||||||
#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
|
|
||||||
#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
|
|
||||||
/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */
|
|
||||||
#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr))
|
|
||||||
|
|
||||||
/* directly map this to the lwip internal functions */
|
|
||||||
#define inet_addr(cp) ipaddr_addr(cp)
|
|
||||||
#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr)
|
|
||||||
#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr))
|
|
||||||
#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen)
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \
|
|
||||||
(target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \
|
|
||||||
(target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \
|
|
||||||
(target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];}
|
|
||||||
#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \
|
|
||||||
(target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \
|
|
||||||
(target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \
|
|
||||||
(target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];}
|
|
||||||
/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */
|
|
||||||
#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr))
|
|
||||||
|
|
||||||
/* directly map this to the lwip internal functions */
|
|
||||||
#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr)
|
|
||||||
#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr))
|
|
||||||
#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen)
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_INET_H */
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_INET_CHKSUM_H
|
|
||||||
#define LWIP_HDR_INET_CHKSUM_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
/** Swap the bytes in an u16_t: much like htons() for little-endian */
|
|
||||||
#ifndef SWAP_BYTES_IN_WORD
|
|
||||||
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
|
|
||||||
/* little endian and PLATFORM_BYTESWAP defined */
|
|
||||||
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
|
|
||||||
#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */
|
|
||||||
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
|
|
||||||
#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8)
|
|
||||||
#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/
|
|
||||||
#endif /* SWAP_BYTES_IN_WORD */
|
|
||||||
|
|
||||||
/** Split an u32_t in two u16_ts and add them up */
|
|
||||||
#ifndef FOLD_U32T
|
|
||||||
#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
/** Function-like macro: same as MEMCPY but returns the checksum of copied data
|
|
||||||
as u16_t */
|
|
||||||
# ifndef LWIP_CHKSUM_COPY
|
|
||||||
# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len)
|
|
||||||
# ifndef LWIP_CHKSUM_COPY_ALGORITHM
|
|
||||||
# define LWIP_CHKSUM_COPY_ALGORITHM 1
|
|
||||||
# endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
|
||||||
# else /* LWIP_CHKSUM_COPY */
|
|
||||||
# define LWIP_CHKSUM_COPY_ALGORITHM 0
|
|
||||||
# endif /* LWIP_CHKSUM_COPY */
|
|
||||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
# define LWIP_CHKSUM_COPY_ALGORITHM 0
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u16_t inet_chksum(const void *dataptr, u16_t len);
|
|
||||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
|
||||||
#if LWIP_CHKSUM_COPY_ALGORITHM
|
|
||||||
u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len);
|
|
||||||
#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip4_addr_t *src, const ip4_addr_t *dest);
|
|
||||||
u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto,
|
|
||||||
u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest);
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip6_addr_t *src, const ip6_addr_t *dest);
|
|
||||||
u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest);
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
|
|
||||||
u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
const ip_addr_t *src, const ip_addr_t *dest);
|
|
||||||
u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|
||||||
u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_INET_H */
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_INIT_H
|
|
||||||
#define LWIP_HDR_INIT_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** X.x.x: Major version of the stack */
|
|
||||||
#define LWIP_VERSION_MAJOR 1U
|
|
||||||
/** x.X.x: Minor version of the stack */
|
|
||||||
#define LWIP_VERSION_MINOR 5U
|
|
||||||
/** x.x.X: Revision of the stack */
|
|
||||||
#define LWIP_VERSION_REVISION 0U
|
|
||||||
/** For release candidates, this is set to 1..254
|
|
||||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
|
||||||
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
|
||||||
#define LWIP_VERSION_RC 0U
|
|
||||||
|
|
||||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
|
||||||
#define LWIP_RC_RELEASE 255U
|
|
||||||
/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */
|
|
||||||
#define LWIP_RC_DEVELOPMENT 0U
|
|
||||||
|
|
||||||
#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE)
|
|
||||||
#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT)
|
|
||||||
#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT))
|
|
||||||
|
|
||||||
/** Provides the version of the stack */
|
|
||||||
#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \
|
|
||||||
LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC)
|
|
||||||
|
|
||||||
/* Modules initialization */
|
|
||||||
void lwip_init(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_INIT_H */
|
|
|
@ -1,304 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP_H__
|
|
||||||
#define LWIP_HDR_IP_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/ip4.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP_PROTO_ICMP 1
|
|
||||||
#define IP_PROTO_IGMP 2
|
|
||||||
#define IP_PROTO_UDP 17
|
|
||||||
#define IP_PROTO_UDPLITE 136
|
|
||||||
#define IP_PROTO_TCP 6
|
|
||||||
|
|
||||||
/** This operates on a void* by loading the first byte */
|
|
||||||
#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4)
|
|
||||||
|
|
||||||
/* This is passed as the destination address to ip_output_if (not
|
|
||||||
to ip_output), meaning that an IP header already is constructed
|
|
||||||
in the pbuf. This is used when TCP retransmits. */
|
|
||||||
#ifdef IP_HDRINCL
|
|
||||||
#undef IP_HDRINCL
|
|
||||||
#endif /* IP_HDRINCL */
|
|
||||||
#define IP_HDRINCL NULL
|
|
||||||
|
|
||||||
/** 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 */
|
|
||||||
#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX
|
|
||||||
#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
#define IP_PCB_ADDRHINT ;u8_t addr_hint
|
|
||||||
#else
|
|
||||||
#define IP_PCB_ADDRHINT
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
|
|
||||||
/* This is the common part of all PCB types. It needs to be at the
|
|
||||||
beginning of a PCB type definition. It is located here so that
|
|
||||||
changes to this common part are made in one location instead of
|
|
||||||
having to change all PCB structs. */
|
|
||||||
#define IP_PCB \
|
|
||||||
/* ip addresses in network byte order */ \
|
|
||||||
ip_addr_t local_ip; \
|
|
||||||
ip_addr_t remote_ip; \
|
|
||||||
/* Socket options */ \
|
|
||||||
u8_t so_options; \
|
|
||||||
/* Type Of Service */ \
|
|
||||||
u8_t tos; \
|
|
||||||
/* Time To Live */ \
|
|
||||||
u8_t ttl \
|
|
||||||
/* link layer address resolution hint */ \
|
|
||||||
IP_PCB_ADDRHINT
|
|
||||||
|
|
||||||
struct ip_pcb {
|
|
||||||
/* Common members of all PCB types */
|
|
||||||
IP_PCB;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Option flags per-socket. These are the same like SO_XXX in sockets.h
|
|
||||||
*/
|
|
||||||
#define SOF_REUSEADDR 0x04U /* allow local address reuse */
|
|
||||||
#define SOF_KEEPALIVE 0x08U /* keep connections alive */
|
|
||||||
#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
|
||||||
|
|
||||||
/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
|
|
||||||
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE)
|
|
||||||
|
|
||||||
/* Global variables of this module, kept in a struct for efficient access using base+index. */
|
|
||||||
struct ip_globals
|
|
||||||
{
|
|
||||||
/** The interface that accepted the packet for the current callback invocation. */
|
|
||||||
struct netif *current_netif;
|
|
||||||
/** The interface that received the packet for the current callback invocation. */
|
|
||||||
struct netif *current_input_netif;
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/** Header of the input packet currently being processed. */
|
|
||||||
struct ip_hdr *current_ip4_header;
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** Header of the input IPv6 packet currently being processed. */
|
|
||||||
struct ip6_hdr *current_ip6_header;
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
/** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */
|
|
||||||
u16_t current_ip_header_tot_len;
|
|
||||||
/** Source IP address of current_header */
|
|
||||||
ip_addr_t current_iphdr_src;
|
|
||||||
/** Destination IP address of current_header */
|
|
||||||
ip_addr_t current_iphdr_dest;
|
|
||||||
};
|
|
||||||
extern struct ip_globals ip_data;
|
|
||||||
|
|
||||||
|
|
||||||
/** Get the interface that accepted the current packet.
|
|
||||||
* This may or may not be the receiving netif, depending on your netif/network setup.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip_current_netif() (ip_data.current_netif)
|
|
||||||
/** Get the interface that received the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip_current_input_netif() (ip_data.current_input_netif)
|
|
||||||
/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */
|
|
||||||
#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len)
|
|
||||||
/** Source IP address of current_header */
|
|
||||||
#define ip_current_src_addr() (&ip_data.current_iphdr_src)
|
|
||||||
/** Destination IP address of current_header */
|
|
||||||
#define ip_current_dest_addr() (&ip_data.current_iphdr_dest)
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
/** Get the IPv4 header of the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header))
|
|
||||||
/** Get the IPv6 header of the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header))
|
|
||||||
/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */
|
|
||||||
#define ip_current_is_v6() (ip6_current_header() != NULL)
|
|
||||||
/** Source IPv6 address of current_header */
|
|
||||||
#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src))
|
|
||||||
/** Destination IPv6 address of current_header */
|
|
||||||
#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest))
|
|
||||||
/** Get the transport layer protocol */
|
|
||||||
#define ip_current_header_proto() (ip_current_is_v6() ? \
|
|
||||||
IP6H_NEXTH(ip6_current_header()) :\
|
|
||||||
IPH_PROTO(ip4_current_header()))
|
|
||||||
/** Get the transport layer header */
|
|
||||||
#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \
|
|
||||||
(const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len()))
|
|
||||||
|
|
||||||
/** Source IP4 address of current_header */
|
|
||||||
#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src))
|
|
||||||
/** Destination IP4 address of current_header */
|
|
||||||
#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest))
|
|
||||||
|
|
||||||
#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
/** Get the IPv4 header of the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header))
|
|
||||||
/** Always returns FALSE when only supporting IPv4 only */
|
|
||||||
#define ip_current_is_v6() 0
|
|
||||||
/** Get the transport layer protocol */
|
|
||||||
#define ip_current_header_proto() IPH_PROTO(ip4_current_header())
|
|
||||||
/** Get the transport layer header */
|
|
||||||
#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len()))
|
|
||||||
/** Source IP4 address of current_header */
|
|
||||||
#define ip4_current_src_addr() (&ip_data.current_iphdr_src)
|
|
||||||
/** Destination IP4 address of current_header */
|
|
||||||
#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest)
|
|
||||||
|
|
||||||
#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
/** Get the IPv6 header of the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header))
|
|
||||||
/** Always returns TRUE when only supporting IPv6 only */
|
|
||||||
#define ip_current_is_v6() 1
|
|
||||||
/** Get the transport layer protocol */
|
|
||||||
#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header())
|
|
||||||
/** Get the transport layer header */
|
|
||||||
#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header()))
|
|
||||||
/** Source IP6 address of current_header */
|
|
||||||
#define ip6_current_src_addr() (&ip_data.current_iphdr_src)
|
|
||||||
/** Destination IP6 address of current_header */
|
|
||||||
#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest)
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/** Union source address of current_header */
|
|
||||||
#define ip_current_src_addr() (&ip_data.current_iphdr_src)
|
|
||||||
/** Union destination address of current_header */
|
|
||||||
#define ip_current_dest_addr() (&ip_data.current_iphdr_dest)
|
|
||||||
|
|
||||||
/** Gets an IP pcb option (SOF_* flags) */
|
|
||||||
#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt))
|
|
||||||
/** Sets an IP pcb option (SOF_* flags) */
|
|
||||||
#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt))
|
|
||||||
/** Resets an IP pcb option (SOF_* flags) */
|
|
||||||
#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt))
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
#define ip_output(p, src, dest, ttl, tos, proto) \
|
|
||||||
(IP_IS_V6(dest) ? \
|
|
||||||
ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \
|
|
||||||
ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto))
|
|
||||||
#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
(IP_IS_V6(dest) ? \
|
|
||||||
ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \
|
|
||||||
ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif))
|
|
||||||
#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
(IP_IS_V6(dest) ? \
|
|
||||||
ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \
|
|
||||||
ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif))
|
|
||||||
#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \
|
|
||||||
(IP_IS_V6(dest) ? \
|
|
||||||
ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \
|
|
||||||
ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint))
|
|
||||||
#define ip_route(src, dest) \
|
|
||||||
(IP_IS_V6(dest) ? \
|
|
||||||
ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \
|
|
||||||
ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src)))
|
|
||||||
#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \
|
|
||||||
ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \
|
|
||||||
ip4_netif_get_local_ip(netif))
|
|
||||||
#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p))
|
|
||||||
|
|
||||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
|
||||||
|
|
||||||
#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#define ip_output(p, src, dest, ttl, tos, proto) \
|
|
||||||
ip4_output(p, src, dest, ttl, tos, proto)
|
|
||||||
#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
ip4_output_if(p, src, dest, ttl, tos, proto, netif)
|
|
||||||
#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
ip4_output_if_src(p, src, dest, ttl, tos, proto, netif)
|
|
||||||
#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \
|
|
||||||
ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint)
|
|
||||||
#define ip_route(src, dest) \
|
|
||||||
ip4_route_src(dest, src)
|
|
||||||
#define ip_netif_get_local_ip(netif, dest) \
|
|
||||||
ip4_netif_get_local_ip(netif)
|
|
||||||
#define ip_debug_print(is_ipv6, p) ip4_debug_print(p)
|
|
||||||
|
|
||||||
#define ip_input ip4_input
|
|
||||||
|
|
||||||
#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#define ip_output(p, src, dest, ttl, tos, proto) \
|
|
||||||
ip6_output(p, src, dest, ttl, tos, proto)
|
|
||||||
#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
ip6_output_if(p, src, dest, ttl, tos, proto, netif)
|
|
||||||
#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \
|
|
||||||
ip6_output_if_src(p, src, dest, ttl, tos, proto, netif)
|
|
||||||
#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \
|
|
||||||
ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint)
|
|
||||||
#define ip_route(src, dest) \
|
|
||||||
ip6_route(src, dest)
|
|
||||||
#define ip_netif_get_local_ip(netif, dest) \
|
|
||||||
ip6_netif_get_local_ip(netif, dest)
|
|
||||||
#define ip_debug_print(is_ipv6, p) ip6_debug_print(p)
|
|
||||||
|
|
||||||
#define ip_input ip6_input
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \
|
|
||||||
(netif) = ip_route(src, dest); \
|
|
||||||
(ipaddr) = ip_netif_get_local_ip(netif, dest); \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP_H__ */
|
|
||||||
|
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP4_H
|
|
||||||
#define LWIP_HDR_IP4_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip4_addr.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
|
|
||||||
#define LWIP_IPV4_SRC_ROUTING 1
|
|
||||||
#else
|
|
||||||
#define LWIP_IPV4_SRC_ROUTING 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Currently, the function ip_output_if_opt() is only used with IGMP */
|
|
||||||
#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP)
|
|
||||||
|
|
||||||
#define IP_HLEN 20
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip_hdr {
|
|
||||||
/* version / header length */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _v_hl);
|
|
||||||
/* type of service */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _tos);
|
|
||||||
/* total length */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _len);
|
|
||||||
/* identification */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _id);
|
|
||||||
/* fragment offset field */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _offset);
|
|
||||||
#define IP_RF 0x8000U /* reserved fragment flag */
|
|
||||||
#define IP_DF 0x4000U /* don't fragment flag */
|
|
||||||
#define IP_MF 0x2000U /* more fragments flag */
|
|
||||||
#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */
|
|
||||||
/* time to live */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _ttl);
|
|
||||||
/* protocol*/
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _proto);
|
|
||||||
/* checksum */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _chksum);
|
|
||||||
/* source and destination IP addresses */
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t src);
|
|
||||||
PACK_STRUCT_FLD_S(ip4_addr_p_t dest);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IPH_V(hdr) ((hdr)->_v_hl >> 4)
|
|
||||||
#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
|
|
||||||
#define IPH_TOS(hdr) ((hdr)->_tos)
|
|
||||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
|
||||||
#define IPH_ID(hdr) ((hdr)->_id)
|
|
||||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
|
||||||
#define IPH_TTL(hdr) ((hdr)->_ttl)
|
|
||||||
#define IPH_PROTO(hdr) ((hdr)->_proto)
|
|
||||||
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
|
|
||||||
|
|
||||||
#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl)))
|
|
||||||
#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
|
|
||||||
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
|
|
||||||
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
|
|
||||||
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
|
|
||||||
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
|
|
||||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
|
|
||||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
|
||||||
|
|
||||||
#define ip_init() /* Compatibility define, no init needed. */
|
|
||||||
struct netif *ip4_route(const ip4_addr_t *dest);
|
|
||||||
#if LWIP_IPV4_SRC_ROUTING
|
|
||||||
struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src);
|
|
||||||
#else /* LWIP_IPV4_SRC_ROUTING */
|
|
||||||
#define ip4_route_src(dest, src) ip4_route(dest)
|
|
||||||
#endif /* LWIP_IPV4_SRC_ROUTING */
|
|
||||||
err_t ip4_input(struct pbuf *p, struct netif *inp);
|
|
||||||
err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|
||||||
u8_t ttl, u8_t tos, u8_t proto);
|
|
||||||
err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|
||||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif);
|
|
||||||
err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|
||||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif);
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|
||||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint);
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
#if IP_OPTIONS_SEND
|
|
||||||
err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|
||||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
|
||||||
u16_t optlen);
|
|
||||||
err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_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 */
|
|
||||||
|
|
||||||
#if LWIP_MULTICAST_TX_OPTIONS
|
|
||||||
void ip4_set_default_multicast_netif(struct netif* default_multicast_netif);
|
|
||||||
#endif /* LWIP_MULTICAST_TX_OPTIONS */
|
|
||||||
|
|
||||||
#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL)
|
|
||||||
|
|
||||||
#if IP_DEBUG
|
|
||||||
void ip4_debug_print(struct pbuf *p);
|
|
||||||
#else
|
|
||||||
#define ip4_debug_print(p)
|
|
||||||
#endif /* IP_DEBUG */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP_H */
|
|
||||||
|
|
||||||
|
|
|
@ -1,253 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP4_ADDR_H
|
|
||||||
#define LWIP_HDR_IP4_ADDR_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This is the aligned version of ip4_addr_t,
|
|
||||||
used as local variable, on the stack, etc. */
|
|
||||||
struct ip4_addr {
|
|
||||||
u32_t addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This is the packed version of ip4_addr_t,
|
|
||||||
used in network headers that are itself packed */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip4_addr_packed {
|
|
||||||
PACK_STRUCT_FIELD(u32_t addr);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** ip4_addr_t uses a struct for convenience only, so that the same defines can
|
|
||||||
* operate both on ip4_addr_t as well as on ip4_addr_p_t. */
|
|
||||||
typedef struct ip4_addr ip4_addr_t;
|
|
||||||
typedef struct ip4_addr_packed ip4_addr_p_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* struct ipaddr2 is used in the definition of the ARP packet format in
|
|
||||||
* order to support compilers that don't have structure packing.
|
|
||||||
*/
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip4_addr2 {
|
|
||||||
PACK_STRUCT_FIELD(u16_t addrw[2]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Forward declaration to not include netif.h */
|
|
||||||
struct netif;
|
|
||||||
|
|
||||||
/** 255.255.255.255 */
|
|
||||||
#define IPADDR_NONE ((u32_t)0xffffffffUL)
|
|
||||||
/** 127.0.0.1 */
|
|
||||||
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
|
|
||||||
/** 0.0.0.0 */
|
|
||||||
#define IPADDR_ANY ((u32_t)0x00000000UL)
|
|
||||||
/** 255.255.255.255 */
|
|
||||||
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
|
|
||||||
|
|
||||||
/* Definitions of the bits in an Internet address integer.
|
|
||||||
|
|
||||||
On subnets, host and network parts are found according to
|
|
||||||
the subnet mask, not these masks. */
|
|
||||||
#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
|
|
||||||
#define IP_CLASSA_NET 0xff000000
|
|
||||||
#define IP_CLASSA_NSHIFT 24
|
|
||||||
#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET)
|
|
||||||
#define IP_CLASSA_MAX 128
|
|
||||||
|
|
||||||
#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
|
|
||||||
#define IP_CLASSB_NET 0xffff0000
|
|
||||||
#define IP_CLASSB_NSHIFT 16
|
|
||||||
#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET)
|
|
||||||
#define IP_CLASSB_MAX 65536
|
|
||||||
|
|
||||||
#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
|
|
||||||
#define IP_CLASSC_NET 0xffffff00
|
|
||||||
#define IP_CLASSC_NSHIFT 8
|
|
||||||
#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET)
|
|
||||||
|
|
||||||
#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
|
|
||||||
#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
|
||||||
#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */
|
|
||||||
#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
|
||||||
#define IP_MULTICAST(a) IP_CLASSD(a)
|
|
||||||
|
|
||||||
#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
|
||||||
#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
|
||||||
|
|
||||||
#define IP_LOOPBACKNET 127 /* official! */
|
|
||||||
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
/** Set an IP address given by the four byte-parts */
|
|
||||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
|
||||||
(ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
|
|
||||||
((u32_t)((b) & 0xff) << 16) | \
|
|
||||||
((u32_t)((c) & 0xff) << 8) | \
|
|
||||||
(u32_t)((d) & 0xff)
|
|
||||||
#else
|
|
||||||
/** Set an IP address given by the four byte-parts.
|
|
||||||
Little-endian version that prevents the use of htonl. */
|
|
||||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
|
||||||
(ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
|
|
||||||
((u32_t)((c) & 0xff) << 16) | \
|
|
||||||
((u32_t)((b) & 0xff) << 8) | \
|
|
||||||
(u32_t)((a) & 0xff)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** MEMCPY-like copying of IP addresses where addresses are known to be
|
|
||||||
* 16-bit-aligned if the port is correctly configured (so a port could define
|
|
||||||
* this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
|
|
||||||
#ifndef IPADDR2_COPY
|
|
||||||
#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Copy IP address - faster than ip4_addr_set: no NULL check */
|
|
||||||
#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
|
|
||||||
/** Safely copy one IP address to another (src may be NULL) */
|
|
||||||
#define ip4_addr_set(dest, src) ((dest)->addr = \
|
|
||||||
((src) == NULL ? 0 : \
|
|
||||||
(src)->addr))
|
|
||||||
/** Set complete address to zero */
|
|
||||||
#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
|
|
||||||
/** Set address to IPADDR_ANY (no need for htonl()) */
|
|
||||||
#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY)
|
|
||||||
/** Set address to loopback address */
|
|
||||||
#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK))
|
|
||||||
/** Check if an address is in the loopback region */
|
|
||||||
#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24))
|
|
||||||
/** Safely copy one IP address to another and change byte order
|
|
||||||
* from host- to network-order. */
|
|
||||||
#define ip4_addr_set_hton(dest, src) ((dest)->addr = \
|
|
||||||
((src) == NULL ? 0:\
|
|
||||||
htonl((src)->addr)))
|
|
||||||
/** IPv4 only: set the IP address given as an u32_t */
|
|
||||||
#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
|
|
||||||
/** IPv4 only: get the IP address as an u32_t */
|
|
||||||
#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
|
|
||||||
|
|
||||||
/** Get the network address by combining host address with netmask */
|
|
||||||
#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if two address are on the same network.
|
|
||||||
*
|
|
||||||
* @arg addr1 IP address 1
|
|
||||||
* @arg addr2 IP address 2
|
|
||||||
* @arg mask network identifier mask
|
|
||||||
* @return !0 if the network identifiers of both address match
|
|
||||||
*/
|
|
||||||
#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
|
|
||||||
(mask)->addr) == \
|
|
||||||
((addr2)->addr & \
|
|
||||||
(mask)->addr))
|
|
||||||
#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
|
|
||||||
|
|
||||||
#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY)
|
|
||||||
#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1)))
|
|
||||||
|
|
||||||
#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif)
|
|
||||||
u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif);
|
|
||||||
|
|
||||||
#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
|
|
||||||
u8_t ip4_addr_netmask_valid(u32_t netmask);
|
|
||||||
|
|
||||||
#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL))
|
|
||||||
|
|
||||||
#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
|
|
||||||
|
|
||||||
#define ip4_addr_debug_print_parts(debug, a, b, c, d) \
|
|
||||||
LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d))
|
|
||||||
#define ip4_addr_debug_print(debug, ipaddr) \
|
|
||||||
ip4_addr_debug_print_parts(debug, \
|
|
||||||
(ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)
|
|
||||||
#define ip4_addr_debug_print_val(debug, ipaddr) \
|
|
||||||
ip4_addr_debug_print_parts(debug, \
|
|
||||||
ip4_addr1_16(&(ipaddr)), \
|
|
||||||
ip4_addr2_16(&(ipaddr)), \
|
|
||||||
ip4_addr3_16(&(ipaddr)), \
|
|
||||||
ip4_addr4_16(&(ipaddr)))
|
|
||||||
|
|
||||||
/* Get one byte from the 4-byte address */
|
|
||||||
#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0])
|
|
||||||
#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1])
|
|
||||||
#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2])
|
|
||||||
#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3])
|
|
||||||
/* These are cast to u16_t, with the intent that they are often arguments
|
|
||||||
* to printf using the U16_F format from cc.h. */
|
|
||||||
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
|
|
||||||
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
|
|
||||||
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
|
|
||||||
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
|
|
||||||
|
|
||||||
#define IP4ADDR_STRLEN_MAX 16
|
|
||||||
#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX
|
|
||||||
|
|
||||||
/** For backwards compatibility */
|
|
||||||
#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr)
|
|
||||||
|
|
||||||
u32_t ipaddr_addr(const char *cp);
|
|
||||||
int ip4addr_aton(const char *cp, ip4_addr_t *addr);
|
|
||||||
/** returns ptr to static buffer; not reentrant! */
|
|
||||||
char *ip4addr_ntoa(const ip4_addr_t *addr);
|
|
||||||
char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP_ADDR_H */
|
|
|
@ -1,197 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 layer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP6_H
|
|
||||||
#define LWIP_HDR_IP6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP6_HLEN 40
|
|
||||||
|
|
||||||
#define IP6_NEXTH_HOPBYHOP 0
|
|
||||||
#define IP6_NEXTH_TCP 6
|
|
||||||
#define IP6_NEXTH_UDP 17
|
|
||||||
#define IP6_NEXTH_ENCAPS 41
|
|
||||||
#define IP6_NEXTH_ROUTING 43
|
|
||||||
#define IP6_NEXTH_FRAGMENT 44
|
|
||||||
#define IP6_NEXTH_ICMP6 58
|
|
||||||
#define IP6_NEXTH_NONE 59
|
|
||||||
#define IP6_NEXTH_DESTOPTS 60
|
|
||||||
#define IP6_NEXTH_UDPLITE 136
|
|
||||||
|
|
||||||
|
|
||||||
/* The IPv6 header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip6_hdr {
|
|
||||||
/* version / traffic class / flow label */
|
|
||||||
PACK_STRUCT_FIELD(u32_t _v_tc_fl);
|
|
||||||
/* payload length */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _plen);
|
|
||||||
/* next header */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _nexth);
|
|
||||||
/* hop limit */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _hoplim);
|
|
||||||
/* source and destination IP addresses */
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t src);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t dest);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Hop-by-hop router alert option. */
|
|
||||||
#define IP6_HBH_HLEN 8
|
|
||||||
#define IP6_PAD1_OPTION 0
|
|
||||||
#define IP6_PADN_ALERT_OPTION 1
|
|
||||||
#define IP6_ROUTER_ALERT_OPTION 5
|
|
||||||
#define IP6_ROUTER_ALERT_VALUE_MLD 0
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip6_hbh_hdr {
|
|
||||||
/* next header */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _nexth);
|
|
||||||
/* header length */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _hlen);
|
|
||||||
/* router alert option type */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _ra_opt_type);
|
|
||||||
/* router alert option data len */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen);
|
|
||||||
/* router alert option data */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _ra_opt_data);
|
|
||||||
/* PadN option type */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _padn_opt_type);
|
|
||||||
/* PadN option data len */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fragment header. */
|
|
||||||
#define IP6_FRAG_HLEN 8
|
|
||||||
#define IP6_FRAG_OFFSET_MASK 0xfff8
|
|
||||||
#define IP6_FRAG_MORE_FLAG 0x0001
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip6_frag_hdr {
|
|
||||||
/* next header */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t _nexth);
|
|
||||||
/* reserved */
|
|
||||||
PACK_STRUCT_FLD_8(u8_t reserved);
|
|
||||||
/* fragment offset */
|
|
||||||
PACK_STRUCT_FIELD(u16_t _fragment_offset);
|
|
||||||
/* fragmented packet identification */
|
|
||||||
PACK_STRUCT_FIELD(u32_t _identification);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f)
|
|
||||||
#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff)
|
|
||||||
#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff)
|
|
||||||
#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen))
|
|
||||||
#define IP6H_NEXTH(hdr) ((hdr)->_nexth)
|
|
||||||
#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6)
|
|
||||||
#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim)
|
|
||||||
|
|
||||||
#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl)))
|
|
||||||
#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen)
|
|
||||||
#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth)
|
|
||||||
#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl)
|
|
||||||
|
|
||||||
|
|
||||||
struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest);
|
|
||||||
const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest);
|
|
||||||
err_t ip6_input(struct pbuf *p, struct netif *inp);
|
|
||||||
err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|
||||||
u8_t hl, u8_t tc, u8_t nexth);
|
|
||||||
err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|
||||||
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
|
||||||
err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|
||||||
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|
||||||
u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint);
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value);
|
|
||||||
#endif /* LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \
|
|
||||||
ip6_select_source_address(netif, dest) : NULL)
|
|
||||||
|
|
||||||
#if IP6_DEBUG
|
|
||||||
void ip6_debug_print(struct pbuf *p);
|
|
||||||
#else
|
|
||||||
#define ip6_debug_print(p)
|
|
||||||
#endif /* IP6_DEBUG */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP6_H */
|
|
|
@ -1,301 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 addresses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
* Structs and macros for handling IPv6 addresses.
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP6_ADDR_H
|
|
||||||
#define LWIP_HDR_IP6_ADDR_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the aligned version of ip6_addr_t,
|
|
||||||
used as local variable, on the stack, etc. */
|
|
||||||
struct ip6_addr {
|
|
||||||
u32_t addr[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This is the packed version of ip6_addr_t,
|
|
||||||
used in network headers that are itself packed */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip6_addr_packed {
|
|
||||||
PACK_STRUCT_FIELD(u32_t addr[4]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct ip6_addr ip6_addr_t;
|
|
||||||
typedef struct ip6_addr_packed ip6_addr_p_t;
|
|
||||||
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
/** Set an IPv6 partial address given by byte-parts. */
|
|
||||||
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
|
|
||||||
(ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \
|
|
||||||
((u32_t)((b) & 0xff) << 16) | \
|
|
||||||
((u32_t)((c) & 0xff) << 8) | \
|
|
||||||
(u32_t)((d) & 0xff)
|
|
||||||
#else
|
|
||||||
/** Set an IPv6 partial address given by byte-parts.
|
|
||||||
Little-endian version, stored in network order (no htonl). */
|
|
||||||
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
|
|
||||||
(ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \
|
|
||||||
((u32_t)((c) & 0xff) << 16) | \
|
|
||||||
((u32_t)((b) & 0xff) << 8) | \
|
|
||||||
(u32_t)((a) & 0xff)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order
|
|
||||||
(use PP_HTONL() for constants) */
|
|
||||||
#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \
|
|
||||||
(ip6addr)->addr[0] = idx0; \
|
|
||||||
(ip6addr)->addr[1] = idx1; \
|
|
||||||
(ip6addr)->addr[2] = idx2; \
|
|
||||||
(ip6addr)->addr[3] = idx3; } while(0)
|
|
||||||
|
|
||||||
/** Access address in 16-bit block */
|
|
||||||
#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0]) >> 16) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0])) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1]) >> 16) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1])) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2]) >> 16) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2])) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3]) >> 16) & 0xffff)
|
|
||||||
#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3])) & 0xffff)
|
|
||||||
|
|
||||||
/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */
|
|
||||||
#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \
|
|
||||||
(dest).addr[1] = (src).addr[1]; \
|
|
||||||
(dest).addr[2] = (src).addr[2]; \
|
|
||||||
(dest).addr[3] = (src).addr[3];}while(0)
|
|
||||||
/** Safely copy one IPv6 address to another (src may be NULL) */
|
|
||||||
#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \
|
|
||||||
(dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \
|
|
||||||
(dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \
|
|
||||||
(dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0)
|
|
||||||
|
|
||||||
/** Set complete address to zero */
|
|
||||||
#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \
|
|
||||||
(ip6addr)->addr[1] = 0; \
|
|
||||||
(ip6addr)->addr[2] = 0; \
|
|
||||||
(ip6addr)->addr[3] = 0;}while(0)
|
|
||||||
|
|
||||||
/** Set address to ipv6 'any' (no need for htonl()) */
|
|
||||||
#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr)
|
|
||||||
/** Set address to ipv6 loopback address */
|
|
||||||
#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \
|
|
||||||
(ip6addr)->addr[1] = 0; \
|
|
||||||
(ip6addr)->addr[2] = 0; \
|
|
||||||
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0)
|
|
||||||
/** Safely copy one IPv6 address to another and change byte order
|
|
||||||
* from host- to network-order. */
|
|
||||||
#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \
|
|
||||||
(dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \
|
|
||||||
(dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \
|
|
||||||
(dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if two IPv6 address are on the same network.
|
|
||||||
*
|
|
||||||
* @arg addr1 IPv6 address 1
|
|
||||||
* @arg addr2 IPv6 address 2
|
|
||||||
* @return !0 if the network identifiers of both address match
|
|
||||||
*/
|
|
||||||
#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
|
||||||
((addr1)->addr[1] == (addr2)->addr[1]))
|
|
||||||
|
|
||||||
#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
|
||||||
((addr1)->addr[1] == (addr2)->addr[1]) && \
|
|
||||||
((addr1)->addr[2] == (addr2)->addr[2]) && \
|
|
||||||
((addr1)->addr[3] == (addr2)->addr[3]))
|
|
||||||
|
|
||||||
#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL)
|
|
||||||
|
|
||||||
#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \
|
|
||||||
((ip6addr).addr[1] == 0) && \
|
|
||||||
((ip6addr).addr[2] == 0) && \
|
|
||||||
((ip6addr).addr[3] == 0))
|
|
||||||
#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr)))
|
|
||||||
|
|
||||||
#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \
|
|
||||||
((ip6addr)->addr[1] == 0UL) && \
|
|
||||||
((ip6addr)->addr[2] == 0UL) && \
|
|
||||||
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
|
||||||
|
|
||||||
#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL))
|
|
||||||
|
|
||||||
#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL))
|
|
||||||
|
|
||||||
#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL))
|
|
||||||
|
|
||||||
#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL))
|
|
||||||
|
|
||||||
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL))
|
|
||||||
#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))
|
|
||||||
#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL))
|
|
||||||
#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL))
|
|
||||||
#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf)
|
|
||||||
#define IP6_MULTICAST_SCOPE_RESERVED 0x0
|
|
||||||
#define IP6_MULTICAST_SCOPE_RESERVED0 0x0
|
|
||||||
#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1
|
|
||||||
#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2
|
|
||||||
#define IP6_MULTICAST_SCOPE_RESERVED3 0x3
|
|
||||||
#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4
|
|
||||||
#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5
|
|
||||||
#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8
|
|
||||||
#define IP6_MULTICAST_SCOPE_GLOBAL 0xe
|
|
||||||
#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf
|
|
||||||
#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL))
|
|
||||||
#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL))
|
|
||||||
#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL))
|
|
||||||
#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL))
|
|
||||||
#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL))
|
|
||||||
#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL))
|
|
||||||
|
|
||||||
/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */
|
|
||||||
#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \
|
|
||||||
((ip6addr)->addr[1] == 0UL) && \
|
|
||||||
((ip6addr)->addr[2] == 0UL) && \
|
|
||||||
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
|
||||||
|
|
||||||
#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
|
||||||
((ip6addr)->addr[1] == 0UL) && \
|
|
||||||
((ip6addr)->addr[2] == 0UL) && \
|
|
||||||
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
|
||||||
#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
|
||||||
(ip6addr)->addr[1] = 0; \
|
|
||||||
(ip6addr)->addr[2] = 0; \
|
|
||||||
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0)
|
|
||||||
|
|
||||||
#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
|
||||||
((ip6addr)->addr[1] == 0UL) && \
|
|
||||||
((ip6addr)->addr[2] == 0UL) && \
|
|
||||||
((ip6addr)->addr[3] == PP_HTONL(0x00000002UL)))
|
|
||||||
#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
|
||||||
(ip6addr)->addr[1] = 0; \
|
|
||||||
(ip6addr)->addr[2] = 0; \
|
|
||||||
(ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0)
|
|
||||||
|
|
||||||
#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
|
||||||
((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \
|
|
||||||
(((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) )
|
|
||||||
|
|
||||||
#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
|
||||||
(ip6addr)->addr[1] = 0; \
|
|
||||||
(ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \
|
|
||||||
(ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0)
|
|
||||||
|
|
||||||
#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
|
||||||
((ip6addr)->addr[1] == 0) && \
|
|
||||||
((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \
|
|
||||||
((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3])))
|
|
||||||
|
|
||||||
/* IPv6 address states. */
|
|
||||||
#define IP6_ADDR_INVALID 0x00
|
|
||||||
#define IP6_ADDR_TENTATIVE 0x08
|
|
||||||
#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */
|
|
||||||
#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */
|
|
||||||
#define IP6_ADDR_VALID 0x10
|
|
||||||
#define IP6_ADDR_PREFERRED 0x30
|
|
||||||
#define IP6_ADDR_DEPRECATED 0x50
|
|
||||||
|
|
||||||
#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID)
|
|
||||||
#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE)
|
|
||||||
#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */
|
|
||||||
#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED)
|
|
||||||
#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED)
|
|
||||||
|
|
||||||
#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \
|
|
||||||
LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \
|
|
||||||
a, b, c, d, e, f, g, h))
|
|
||||||
#define ip6_addr_debug_print(debug, ipaddr) \
|
|
||||||
ip6_addr_debug_print_parts(debug, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \
|
|
||||||
(ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)
|
|
||||||
#define ip6_addr_debug_print_val(debug, ipaddr) \
|
|
||||||
ip6_addr_debug_print_parts(debug, \
|
|
||||||
IP6_ADDR_BLOCK1(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK2(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK3(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK4(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK5(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK6(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK7(&(ipaddr)), \
|
|
||||||
IP6_ADDR_BLOCK8(&(ipaddr)))
|
|
||||||
|
|
||||||
#define IP6ADDR_STRLEN_MAX 46
|
|
||||||
|
|
||||||
int ip6addr_aton(const char *cp, ip6_addr_t *addr);
|
|
||||||
/** returns ptr to static buffer; not reentrant! */
|
|
||||||
char *ip6addr_ntoa(const ip6_addr_t *addr);
|
|
||||||
char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP6_ADDR_H */
|
|
|
@ -1,120 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* IPv6 fragmentation and reassembly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP6_FRAG_H
|
|
||||||
#define LWIP_HDR_IP6_FRAG_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to
|
|
||||||
* be enabled (to not overwrite part of the data). When enabled, the IPv6 header
|
|
||||||
* is copied instead of referencing it, which gives more room for struct ip6_reass_helper */
|
|
||||||
#ifndef IPV6_FRAG_COPYHEADER
|
|
||||||
#define IPV6_FRAG_COPYHEADER 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The IPv6 reassembly timer interval in milliseconds. */
|
|
||||||
#define IP6_REASS_TMR_INTERVAL 1000
|
|
||||||
|
|
||||||
/* Copy the complete header of the first fragment to struct ip6_reassdata
|
|
||||||
or just point to its original location in the first pbuf? */
|
|
||||||
#if IPV6_FRAG_COPYHEADER
|
|
||||||
#define IPV6_FRAG_HDRPTR
|
|
||||||
#define IPV6_FRAG_HDRREF(hdr) (&(hdr))
|
|
||||||
#else /* IPV6_FRAG_COPYHEADER */
|
|
||||||
#define IPV6_FRAG_HDRPTR *
|
|
||||||
#define IPV6_FRAG_HDRREF(hdr) (hdr)
|
|
||||||
#endif /* IPV6_FRAG_COPYHEADER */
|
|
||||||
|
|
||||||
/* IPv6 reassembly helper struct.
|
|
||||||
* This is exported because memp needs to know the size.
|
|
||||||
*/
|
|
||||||
struct ip6_reassdata {
|
|
||||||
struct ip6_reassdata *next;
|
|
||||||
struct pbuf *p;
|
|
||||||
struct ip6_hdr IPV6_FRAG_HDRPTR iphdr;
|
|
||||||
u32_t identification;
|
|
||||||
u16_t datagram_len;
|
|
||||||
u8_t nexth;
|
|
||||||
u8_t timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ip6_reass_init() /* Compatibility define */
|
|
||||||
void ip6_reass_tmr(void);
|
|
||||||
struct pbuf * ip6_reass(struct pbuf *p);
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
|
||||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
|
||||||
* that points into the original pbuf. */
|
|
||||||
#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED
|
|
||||||
#define LWIP_PBUF_CUSTOM_REF_DEFINED
|
|
||||||
struct pbuf_custom_ref {
|
|
||||||
/** 'base class' */
|
|
||||||
struct pbuf_custom pc;
|
|
||||||
/** pointer to the original pbuf that is referenced */
|
|
||||||
struct pbuf *original;
|
|
||||||
};
|
|
||||||
#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */
|
|
||||||
|
|
||||||
err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest);
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP6_FRAG_H */
|
|
|
@ -1,318 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_IP_ADDR_H__
|
|
||||||
#define LWIP_HDR_IP_ADDR_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
|
|
||||||
#include "lwip/ip4_addr.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** These are the values for ip_addr_t.type */
|
|
||||||
#define IPADDR_TYPE_V4 0U
|
|
||||||
#define IPADDR_TYPE_V6 6U
|
|
||||||
#define IPADDR_TYPE_ANY 46U
|
|
||||||
|
|
||||||
#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4)
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
/** A union struct for both IP version's addresses.
|
|
||||||
* ATTENTION: watch out for its size when adding IPv6 address scope!
|
|
||||||
*/
|
|
||||||
typedef struct _ip_addr {
|
|
||||||
union {
|
|
||||||
ip6_addr_t ip6;
|
|
||||||
ip4_addr_t ip4;
|
|
||||||
} u_addr;
|
|
||||||
u8_t type;
|
|
||||||
} ip_addr_t;
|
|
||||||
|
|
||||||
extern const ip_addr_t ip_addr_any_type;
|
|
||||||
|
|
||||||
#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 }
|
|
||||||
#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 }
|
|
||||||
|
|
||||||
#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY)
|
|
||||||
#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY }
|
|
||||||
|
|
||||||
#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6)
|
|
||||||
#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr)))
|
|
||||||
|
|
||||||
#define IP_V6_EQ_PART(ipaddr, WORD, VAL) (ip_2_ip6(ipaddr)->addr[WORD] == htonl(VAL))
|
|
||||||
#define IP_IS_V4MAPPEDV6(ipaddr) (IP_IS_V6(ipaddr) && IP_V6_EQ_PART(ipaddr, 0, 0) && IP_V6_EQ_PART(ipaddr, 1, 0) && IP_V6_EQ_PART(ipaddr, 2, 0x0000FFFF))
|
|
||||||
|
|
||||||
#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0)
|
|
||||||
#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0)
|
|
||||||
#define IP_GET_TYPE(ipaddr) ((ipaddr)->type)
|
|
||||||
|
|
||||||
#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr))
|
|
||||||
#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr))
|
|
||||||
|
|
||||||
/* Convert generic ip address to specific protocol version */
|
|
||||||
#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6))
|
|
||||||
#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4))
|
|
||||||
|
|
||||||
#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \
|
|
||||||
IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0)
|
|
||||||
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \
|
|
||||||
IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0)
|
|
||||||
|
|
||||||
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
|
||||||
ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
|
|
||||||
ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0)
|
|
||||||
#define ip_addr_copy_from_ip6(dest, src) do{ \
|
|
||||||
ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0)
|
|
||||||
#define ip_addr_copy_from_ip4(dest, src) do{ \
|
|
||||||
ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0)
|
|
||||||
#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \
|
|
||||||
IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0)
|
|
||||||
#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && !IP_IS_V6(ipaddr)) ? \
|
|
||||||
ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0)
|
|
||||||
|
|
||||||
#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \
|
|
||||||
ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \
|
|
||||||
ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0)
|
|
||||||
|
|
||||||
#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src)
|
|
||||||
#define ip_addr_set_zero(ipaddr) do{ \
|
|
||||||
ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0)
|
|
||||||
#define ip_addr_set_zero_ip4(ipaddr) do{ \
|
|
||||||
ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0)
|
|
||||||
#define ip_addr_set_zero_ip6(ipaddr) do{ \
|
|
||||||
ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0)
|
|
||||||
#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \
|
|
||||||
ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \
|
|
||||||
ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0)
|
|
||||||
#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \
|
|
||||||
ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \
|
|
||||||
ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0)
|
|
||||||
#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \
|
|
||||||
ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \
|
|
||||||
ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0)
|
|
||||||
#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \
|
|
||||||
ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \
|
|
||||||
ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0)
|
|
||||||
#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \
|
|
||||||
0 : \
|
|
||||||
ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask))
|
|
||||||
#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \
|
|
||||||
ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \
|
|
||||||
ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2))))
|
|
||||||
#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \
|
|
||||||
ip6_addr_isany(ip_2_ip6(ipaddr)) : \
|
|
||||||
ip4_addr_isany(ip_2_ip4(ipaddr)))
|
|
||||||
#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \
|
|
||||||
ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \
|
|
||||||
ip4_addr_isany_val(*ip_2_ip4(&(ipaddr))))
|
|
||||||
#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \
|
|
||||||
0 : \
|
|
||||||
ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif))
|
|
||||||
#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \
|
|
||||||
ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \
|
|
||||||
ip4_addr_ismulticast(ip_2_ip4(ipaddr)))
|
|
||||||
#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \
|
|
||||||
ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \
|
|
||||||
ip4_addr_isloopback(ip_2_ip4(ipaddr)))
|
|
||||||
#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \
|
|
||||||
ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \
|
|
||||||
ip4_addr_islinklocal(ip_2_ip4(ipaddr)))
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \
|
|
||||||
ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \
|
|
||||||
ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0)
|
|
||||||
#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \
|
|
||||||
ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \
|
|
||||||
ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0)
|
|
||||||
#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \
|
|
||||||
((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))))
|
|
||||||
#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \
|
|
||||||
((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen)))
|
|
||||||
int ipaddr_aton(const char *cp, ip_addr_t *addr);
|
|
||||||
|
|
||||||
/* Map an IPv4 ip_addr into an IPV6 ip_addr, using format
|
|
||||||
defined in RFC4291 2.5.5.2.
|
|
||||||
|
|
||||||
Safe to call when dest==src.
|
|
||||||
*/
|
|
||||||
#define ip_addr_make_ip4_mapped_ip6(dest, src) do { \
|
|
||||||
u32_t tmp = ip_2_ip4(src)->addr; \
|
|
||||||
IP_ADDR6((dest), 0x0, 0x0, htonl(0x0000FFFF), tmp); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/* Convert an IPv4 mapped V6 address to an IPV4 address.
|
|
||||||
|
|
||||||
Check IP_IS_V4MAPPEDV6(src) before using this.
|
|
||||||
|
|
||||||
Safe to call when dest == src.
|
|
||||||
*/
|
|
||||||
#define ip_addr_ip4_from_mapped_ip6(dest, src) do { \
|
|
||||||
ip_2_ip4(dest)->addr = ip_2_ip6(src)->addr[3]; \
|
|
||||||
IP_SET_TYPE(dest, IPADDR_TYPE_V4); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#else /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1
|
|
||||||
#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
typedef ip4_addr_t ip_addr_t;
|
|
||||||
#define IPADDR4_INIT(u32val) { u32val }
|
|
||||||
#define IP_IS_V6_VAL(ipaddr) 0
|
|
||||||
#define IP_IS_V6(ipaddr) 0
|
|
||||||
#define IP_IS_ANY_TYPE_VAL(ipaddr) 0
|
|
||||||
#define IP_SET_TYPE_VAL(ipaddr, iptype)
|
|
||||||
#define IP_SET_TYPE(ipaddr, iptype)
|
|
||||||
#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4
|
|
||||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
|
||||||
#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d)
|
|
||||||
|
|
||||||
#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src)
|
|
||||||
#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src)
|
|
||||||
#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val)
|
|
||||||
#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr))
|
|
||||||
#define ip_addr_set(dest, src) ip4_addr_set(dest, src)
|
|
||||||
#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src)
|
|
||||||
#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr)
|
|
||||||
#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr)
|
|
||||||
#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr)
|
|
||||||
#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr)
|
|
||||||
#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src)
|
|
||||||
#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask)
|
|
||||||
#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask)
|
|
||||||
#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2)
|
|
||||||
#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr)
|
|
||||||
#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr)
|
|
||||||
#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr)
|
|
||||||
#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr)
|
|
||||||
#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif)
|
|
||||||
#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr)
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr)
|
|
||||||
#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr)
|
|
||||||
#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr)
|
|
||||||
#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen)
|
|
||||||
#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr)
|
|
||||||
|
|
||||||
#else /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
typedef ip6_addr_t ip_addr_t;
|
|
||||||
#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } }
|
|
||||||
#define IP_IS_V6_VAL(ipaddr) 1
|
|
||||||
#define IP_IS_V6(ipaddr) 1
|
|
||||||
#define IP_IS_ANY_TYPE_VAL(ipaddr) 0
|
|
||||||
#define IP_SET_TYPE_VAL(ipaddr, iptype)
|
|
||||||
#define IP_SET_TYPE(ipaddr, iptype)
|
|
||||||
#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6
|
|
||||||
#define ip_2_ip6(ipaddr) (ipaddr)
|
|
||||||
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3)
|
|
||||||
|
|
||||||
#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src)
|
|
||||||
#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src)
|
|
||||||
#define ip_addr_set(dest, src) ip6_addr_set(dest, src)
|
|
||||||
#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src)
|
|
||||||
#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr)
|
|
||||||
#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr)
|
|
||||||
#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr)
|
|
||||||
#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr)
|
|
||||||
#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src)
|
|
||||||
#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target)
|
|
||||||
#define ip_addr_netcmp(addr1, addr2, mask) 0
|
|
||||||
#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2)
|
|
||||||
#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr)
|
|
||||||
#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr)
|
|
||||||
#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr)
|
|
||||||
#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr)
|
|
||||||
#define ip_addr_isbroadcast(addr, netif) 0
|
|
||||||
#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr)
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr)
|
|
||||||
#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr)
|
|
||||||
#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr)
|
|
||||||
#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen)
|
|
||||||
#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr)
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
extern const ip_addr_t ip_addr_any;
|
|
||||||
extern const ip_addr_t ip_addr_broadcast;
|
|
||||||
|
|
||||||
/** IP_ADDR_ can be used as a fixed/const ip_addr_t
|
|
||||||
* for the IPv4 wildcard and the broadcast address
|
|
||||||
*/
|
|
||||||
#define IP_ADDR_ANY (&ip_addr_any)
|
|
||||||
#define IP_ADDR_BROADCAST (&ip_addr_broadcast)
|
|
||||||
/** IP4_ADDR_ can be used as a fixed/const ip4_addr_t
|
|
||||||
* for the wildcard and the broadcast address
|
|
||||||
*/
|
|
||||||
#define IP4_ADDR_ANY (ip_2_ip4(&ip_addr_any))
|
|
||||||
#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast))
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4*/
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
|
|
||||||
extern const ip_addr_t ip6_addr_any;
|
|
||||||
|
|
||||||
/** IP6_ADDR_ANY can be used as a fixed ip_addr_t
|
|
||||||
* for the IPv6 wildcard address
|
|
||||||
*/
|
|
||||||
#define IP6_ADDR_ANY (&ip6_addr_any)
|
|
||||||
/** IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t
|
|
||||||
* for the IPv6 wildcard address
|
|
||||||
*/
|
|
||||||
#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any))
|
|
||||||
|
|
||||||
#if !LWIP_IPV4
|
|
||||||
/** Just a little upgrade-helper for IPv6-only configurations: */
|
|
||||||
#define IP_ADDR_ANY IP6_ADDR_ANY
|
|
||||||
#endif /* !LWIP_IPV4 */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
#define IP_ANY_TYPE (&ip_addr_any_type)
|
|
||||||
#else
|
|
||||||
#define IP_ANY_TYPE IP_ADDR_ANY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP_ADDR_H__ */
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_IP_FRAG_H
|
|
||||||
#define LWIP_HDR_IP_FRAG_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if IP_REASSEMBLY
|
|
||||||
/* The IP reassembly timer interval in milliseconds. */
|
|
||||||
#define IP_TMR_INTERVAL 1000
|
|
||||||
|
|
||||||
/* IP reassembly helper struct.
|
|
||||||
* This is exported because memp needs to know the size.
|
|
||||||
*/
|
|
||||||
struct ip_reassdata {
|
|
||||||
struct ip_reassdata *next;
|
|
||||||
struct pbuf *p;
|
|
||||||
struct ip_hdr iphdr;
|
|
||||||
u16_t datagram_len;
|
|
||||||
u8_t flags;
|
|
||||||
u8_t timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ip_reass_init(void);
|
|
||||||
void ip_reass_tmr(void);
|
|
||||||
struct pbuf * ip4_reass(struct pbuf *p);
|
|
||||||
#endif /* IP_REASSEMBLY */
|
|
||||||
|
|
||||||
#if IP_FRAG
|
|
||||||
#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
|
||||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
|
||||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
|
||||||
* that points into the original pbuf. */
|
|
||||||
#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED
|
|
||||||
#define LWIP_PBUF_CUSTOM_REF_DEFINED
|
|
||||||
struct pbuf_custom_ref {
|
|
||||||
/** 'base class' */
|
|
||||||
struct pbuf_custom pc;
|
|
||||||
/** pointer to the original pbuf that is referenced */
|
|
||||||
struct pbuf *original;
|
|
||||||
};
|
|
||||||
#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */
|
|
||||||
#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
|
||||||
|
|
||||||
err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest);
|
|
||||||
#endif /* IP_FRAG */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_IP_FRAG_H */
|
|
|
@ -1,139 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_MEM_H
|
|
||||||
#define LWIP_HDR_MEM_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MEM_LIBC_MALLOC
|
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
|
||||||
|
|
||||||
typedef size_t mem_size_t;
|
|
||||||
#define MEM_SIZE_F SZT_F
|
|
||||||
|
|
||||||
/* aliases for C library malloc() */
|
|
||||||
#define mem_init()
|
|
||||||
/* in case C library malloc() needs extra protection,
|
|
||||||
* allow these defines to be overridden.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef mem_free
|
|
||||||
#define mem_free free
|
|
||||||
#endif
|
|
||||||
/**
|
|
||||||
* lwip_malloc: if CONFIG_ALLOC_MEMORY_IN_SPIRAM_FIRST is enabled, Try to
|
|
||||||
* allocate memory for lwip in SPIRAM firstly. If failed, try to allocate
|
|
||||||
* internal memory then.
|
|
||||||
*/
|
|
||||||
#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
|
|
||||||
#ifndef mem_malloc
|
|
||||||
#define mem_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
|
|
||||||
#endif
|
|
||||||
#ifndef mem_calloc
|
|
||||||
#define mem_calloc(n, size) heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifndef mem_malloc
|
|
||||||
#define mem_malloc malloc
|
|
||||||
#endif
|
|
||||||
#ifndef mem_calloc
|
|
||||||
#define mem_calloc calloc
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Since there is no C library allocation function to shrink memory without
|
|
||||||
moving it, define this to nothing. */
|
|
||||||
#ifndef mem_trim
|
|
||||||
#define mem_trim(mem, size) (mem)
|
|
||||||
#endif
|
|
||||||
#else /* MEM_LIBC_MALLOC */
|
|
||||||
|
|
||||||
/* MEM_SIZE would have to be aligned, but using 64000 here instead of
|
|
||||||
* 65535 leaves some room for alignment...
|
|
||||||
*/
|
|
||||||
#if MEM_SIZE > 64000L
|
|
||||||
typedef u32_t mem_size_t;
|
|
||||||
#define MEM_SIZE_F U32_F
|
|
||||||
#else
|
|
||||||
typedef u16_t mem_size_t;
|
|
||||||
#define MEM_SIZE_F U16_F
|
|
||||||
#endif /* MEM_SIZE > 64000 */
|
|
||||||
|
|
||||||
#if MEM_USE_POOLS
|
|
||||||
/** mem_init is not used when using pools instead of a heap */
|
|
||||||
#define mem_init()
|
|
||||||
/** mem_trim is not used when using pools instead of a heap:
|
|
||||||
we can't free part of a pool element and don't want to copy the rest */
|
|
||||||
#define mem_trim(mem, size) (mem)
|
|
||||||
#else /* MEM_USE_POOLS */
|
|
||||||
/* lwIP alternative malloc */
|
|
||||||
void mem_init(void);
|
|
||||||
void *mem_trim(void *mem, mem_size_t size);
|
|
||||||
#endif /* MEM_USE_POOLS */
|
|
||||||
void *mem_malloc(mem_size_t size);
|
|
||||||
void *mem_calloc(mem_size_t count, mem_size_t size);
|
|
||||||
void mem_free(void *mem);
|
|
||||||
#endif /* MEM_LIBC_MALLOC */
|
|
||||||
|
|
||||||
/** Calculate memory size for an aligned buffer - returns the next highest
|
|
||||||
* multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and
|
|
||||||
* LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4).
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_MEM_ALIGN_SIZE
|
|
||||||
#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Calculate safe memory size for an aligned buffer when using an unaligned
|
|
||||||
* type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the
|
|
||||||
* start (e.g. if buffer is u8_t[] and actual data will be u32_t*)
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_MEM_ALIGN_BUFFER
|
|
||||||
#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT
|
|
||||||
* so that ADDR % MEM_ALIGNMENT == 0
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_MEM_ALIGN
|
|
||||||
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_MEM_H */
|
|
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_MEMP_H
|
|
||||||
#define LWIP_HDR_MEMP_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* run once with empty definition to handle all custom includes in lwippools.h */
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc)
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
|
|
||||||
/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */
|
|
||||||
typedef enum {
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
MEMP_MAX
|
|
||||||
} memp_t;
|
|
||||||
|
|
||||||
#include "lwip/priv/memp_priv.h"
|
|
||||||
|
|
||||||
/* Private mempools example:
|
|
||||||
* .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool);
|
|
||||||
* .c:
|
|
||||||
* - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description")
|
|
||||||
* - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool);
|
|
||||||
* - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool);
|
|
||||||
* - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem);
|
|
||||||
*
|
|
||||||
* To relocate a pool, declare it as extern in cc.h. Example for GCC:
|
|
||||||
* extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[];
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern const struct memp_desc* const memp_pools[MEMP_MAX];
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name
|
|
||||||
|
|
||||||
#if MEMP_MEM_MALLOC
|
|
||||||
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
|
|
||||||
#define memp_init()
|
|
||||||
#if ESP_STATS_MEM
|
|
||||||
static inline void* memp_malloc(int type)
|
|
||||||
{
|
|
||||||
ESP_CNT_MEM_MALLOC_INC(type);
|
|
||||||
return mem_malloc(memp_pools[type]->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void memp_free(int type, void *mem)
|
|
||||||
{
|
|
||||||
ESP_CNT_MEM_FREE_INC(type);
|
|
||||||
mem_free(mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#define memp_malloc(type) mem_malloc(memp_pools[type]->size); ESP_CNT_MEM_MALLOC_INC(type)
|
|
||||||
//#define memp_free(type, mem) mem_free(mem); ESP_CNT_MEM_FREE_INC(type)
|
|
||||||
#else
|
|
||||||
#define memp_malloc(type) mem_malloc(memp_pools[type]->size)
|
|
||||||
#define memp_free(type, mem) mem_free(mem)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
|
|
||||||
const struct memp_desc memp_ ## name = { \
|
|
||||||
LWIP_MEM_ALIGN_SIZE(size) \
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_INIT(name)
|
|
||||||
#define LWIP_MEMPOOL_ALLOC(name) mem_malloc(memp_ ## name.size)
|
|
||||||
#define LWIP_MEMPOOL_FREE(name, x) mem_free(x)
|
|
||||||
|
|
||||||
#else /* MEMP_MEM_MALLOC */
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) u8_t memp_memory_ ## name ## _base \
|
|
||||||
[((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \
|
|
||||||
\
|
|
||||||
static struct memp *memp_tab_ ## name; \
|
|
||||||
\
|
|
||||||
const struct memp_desc memp_ ## name = { \
|
|
||||||
LWIP_MEM_ALIGN_SIZE(size), \
|
|
||||||
(num), \
|
|
||||||
DECLARE_LWIP_MEMPOOL_DESC(desc) \
|
|
||||||
memp_memory_ ## name ## _base, \
|
|
||||||
&memp_tab_ ## name \
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name)
|
|
||||||
#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name)
|
|
||||||
#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x))
|
|
||||||
|
|
||||||
#if MEM_USE_POOLS
|
|
||||||
/** This structure is used to save the pool one element came from. */
|
|
||||||
struct memp_malloc_helper
|
|
||||||
{
|
|
||||||
memp_t poolnr;
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
u16_t size;
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* MEM_USE_POOLS */
|
|
||||||
|
|
||||||
void memp_init(void);
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
void *memp_malloc_fn(memp_t type, const char* file, const int line);
|
|
||||||
#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
void *memp_malloc(memp_t type);
|
|
||||||
#endif
|
|
||||||
void memp_free(memp_t type, void *mem);
|
|
||||||
|
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_MEMP_H */
|
|
|
@ -1,119 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
|
||||||
* No support for MLDv2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_MLD6_H
|
|
||||||
#define LWIP_HDR_MLD6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct mld_group {
|
|
||||||
/** next link */
|
|
||||||
struct mld_group *next;
|
|
||||||
/** interface on which the group is active */
|
|
||||||
struct netif *netif;
|
|
||||||
/** multicast address */
|
|
||||||
ip6_addr_t group_address;
|
|
||||||
/** signifies we were the last person to report */
|
|
||||||
u8_t last_reporter_flag;
|
|
||||||
/** current state of the group */
|
|
||||||
u8_t group_state;
|
|
||||||
/** timer for reporting */
|
|
||||||
u16_t timer;
|
|
||||||
/** counter of simultaneous uses */
|
|
||||||
u8_t use;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Multicast listener report/query/done message header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct mld_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u16_t max_resp_delay);
|
|
||||||
PACK_STRUCT_FIELD(u16_t reserved);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MLD6_TMR_INTERVAL 100 /* Milliseconds */
|
|
||||||
|
|
||||||
/* MAC Filter Actions, these are passed to a netif's
|
|
||||||
* mld_mac_filter callback function. */
|
|
||||||
#define MLD6_DEL_MAC_FILTER 0
|
|
||||||
#define MLD6_ADD_MAC_FILTER 1
|
|
||||||
|
|
||||||
|
|
||||||
err_t mld6_stop(struct netif *netif);
|
|
||||||
void mld6_report_groups(struct netif *netif);
|
|
||||||
void mld6_tmr(void);
|
|
||||||
struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr);
|
|
||||||
void mld6_input(struct pbuf *p, struct netif *inp);
|
|
||||||
err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr);
|
|
||||||
err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr);
|
|
||||||
err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr);
|
|
||||||
err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_MLD6_H */
|
|
|
@ -1,365 +0,0 @@
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Neighbor discovery and stateless address autoconfiguration for IPv6.
|
|
||||||
* Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
|
||||||
* (Address autoconfiguration).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
|
||||||
*
|
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
|
||||||
* <delamer@inicotech.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_ND6_H
|
|
||||||
#define LWIP_HDR_ND6_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Struct for tables. */
|
|
||||||
struct nd6_neighbor_cache_entry {
|
|
||||||
ip6_addr_t next_hop_address;
|
|
||||||
struct netif * netif;
|
|
||||||
u8_t lladdr[NETIF_MAX_HWADDR_LEN];
|
|
||||||
/*u32_t pmtu;*/
|
|
||||||
#if LWIP_ND6_QUEUEING
|
|
||||||
/** Pointer to queue of pending outgoing packets on this entry. */
|
|
||||||
struct nd6_q_entry *q;
|
|
||||||
#else /* LWIP_ND6_QUEUEING */
|
|
||||||
/** Pointer to a single pending outgoing packet on this entry. */
|
|
||||||
struct pbuf *q;
|
|
||||||
#endif /* LWIP_ND6_QUEUEING */
|
|
||||||
u8_t state;
|
|
||||||
u8_t isrouter;
|
|
||||||
union {
|
|
||||||
u32_t reachable_time;
|
|
||||||
u32_t delay_time;
|
|
||||||
u32_t probes_sent;
|
|
||||||
u32_t stale_time;
|
|
||||||
} counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nd6_destination_cache_entry {
|
|
||||||
ip6_addr_t destination_addr;
|
|
||||||
ip6_addr_t next_hop_addr;
|
|
||||||
u16_t pmtu;
|
|
||||||
u32_t age;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nd6_prefix_list_entry {
|
|
||||||
ip6_addr_t prefix;
|
|
||||||
struct netif * netif;
|
|
||||||
u32_t invalidation_timer;
|
|
||||||
#if LWIP_IPV6_AUTOCONFIG
|
|
||||||
u8_t flags;
|
|
||||||
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
|
|
||||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
|
|
||||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
|
|
||||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nd6_router_list_entry {
|
|
||||||
struct nd6_neighbor_cache_entry * neighbor_entry;
|
|
||||||
u32_t invalidation_timer;
|
|
||||||
u8_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum nd6_neighbor_cache_entry_state {
|
|
||||||
ND6_NO_ENTRY = 0,
|
|
||||||
ND6_INCOMPLETE,
|
|
||||||
ND6_REACHABLE,
|
|
||||||
ND6_STALE,
|
|
||||||
ND6_DELAY,
|
|
||||||
ND6_PROBE
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_ND6_QUEUEING
|
|
||||||
/** struct for queueing outgoing packets for unknown address
|
|
||||||
* defined here to be accessed by memp.h
|
|
||||||
*/
|
|
||||||
struct nd6_q_entry {
|
|
||||||
struct nd6_q_entry *next;
|
|
||||||
struct pbuf *p;
|
|
||||||
};
|
|
||||||
#endif /* LWIP_ND6_QUEUEING */
|
|
||||||
|
|
||||||
/** Neighbor solicitation message header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ns_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reserved);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t target_address);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Neighbor advertisement message header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct na_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t flags);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t reserved[3]);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t target_address);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
#define ND6_FLAG_ROUTER (0x80)
|
|
||||||
#define ND6_FLAG_SOLICITED (0x40)
|
|
||||||
#define ND6_FLAG_OVERRIDE (0x20)
|
|
||||||
|
|
||||||
/** Router solicitation message header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct rs_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reserved);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Router advertisement message header. */
|
|
||||||
#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80)
|
|
||||||
#define ND6_RA_FLAG_OTHER_CONFIG (0x40)
|
|
||||||
#define ND6_RA_FLAG_HOME_AGENT (0x20)
|
|
||||||
#define ND6_RA_PREFERENCE_MASK (0x18)
|
|
||||||
#define ND6_RA_PREFERENCE_HIGH (0x08)
|
|
||||||
#define ND6_RA_PREFERENCE_MEDIUM (0x00)
|
|
||||||
#define ND6_RA_PREFERENCE_LOW (0x18)
|
|
||||||
#define ND6_RA_PREFERENCE_DISABLED (0x10)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ra_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t current_hop_limit);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t flags);
|
|
||||||
PACK_STRUCT_FIELD(u16_t router_lifetime);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reachable_time);
|
|
||||||
PACK_STRUCT_FIELD(u32_t retrans_timer);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Redirect message header. */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct redirect_header {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t reserved);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t target_address);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address);
|
|
||||||
/* Options follow. */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Link-layer address option. */
|
|
||||||
#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01)
|
|
||||||
#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct lladdr_option {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Prefix information option. */
|
|
||||||
#define ND6_OPTION_TYPE_PREFIX_INFO (0x03)
|
|
||||||
#define ND6_PREFIX_FLAG_ON_LINK (0x80)
|
|
||||||
#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40)
|
|
||||||
#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20)
|
|
||||||
#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct prefix_option {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t prefix_length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t flags);
|
|
||||||
PACK_STRUCT_FIELD(u32_t valid_lifetime);
|
|
||||||
PACK_STRUCT_FIELD(u32_t preferred_lifetime);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t reserved2[3]);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t site_prefix_length);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t prefix);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Redirected header option. */
|
|
||||||
#define ND6_OPTION_TYPE_REDIR_HDR (0x04)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct redirected_header_option {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t reserved[6]);
|
|
||||||
/* Portion of redirected packet follows. */
|
|
||||||
/* PACK_STRUCT_FLD_8(u8_t redirected[8]); */
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** MTU option. */
|
|
||||||
#define ND6_OPTION_TYPE_MTU (0x05)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct mtu_option {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t length);
|
|
||||||
PACK_STRUCT_FIELD(u16_t reserved);
|
|
||||||
PACK_STRUCT_FIELD(u32_t mtu);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Route information option. */
|
|
||||||
#define ND6_OPTION_TYPE_ROUTE_INFO (24)
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct route_option {
|
|
||||||
PACK_STRUCT_FLD_8(u8_t type);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t prefix_length);
|
|
||||||
PACK_STRUCT_FLD_8(u8_t preference);
|
|
||||||
PACK_STRUCT_FIELD(u32_t route_lifetime);
|
|
||||||
PACK_STRUCT_FLD_S(ip6_addr_p_t prefix);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** 1 second period */
|
|
||||||
#define ND6_TMR_INTERVAL 1000
|
|
||||||
|
|
||||||
/* Router tables. */
|
|
||||||
/* TODO make these static? and entries accessible through API? */
|
|
||||||
extern struct nd6_neighbor_cache_entry neighbor_cache[];
|
|
||||||
extern struct nd6_destination_cache_entry destination_cache[];
|
|
||||||
extern struct nd6_prefix_list_entry prefix_list[];
|
|
||||||
extern struct nd6_router_list_entry default_router_list[];
|
|
||||||
|
|
||||||
/* Default values, can be updated by a RA message. */
|
|
||||||
extern u32_t reachable_time;
|
|
||||||
extern u32_t retrans_timer;
|
|
||||||
|
|
||||||
void nd6_tmr(void);
|
|
||||||
void nd6_input(struct pbuf *p, struct netif *inp);
|
|
||||||
s8_t nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif);
|
|
||||||
s8_t nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif);
|
|
||||||
u16_t nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif);
|
|
||||||
err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p);
|
|
||||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
|
||||||
void nd6_reachability_hint(const ip6_addr_t * ip6addr);
|
|
||||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
/** set nd6 callback when ipv6 addr state pref*/
|
|
||||||
void nd6_set_cb(struct netif *netif, void (*cb)(struct netif *netif, u8_t ip_index));
|
|
||||||
#endif
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_ND6_H */
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_NETBUF_H
|
|
||||||
#define LWIP_HDR_NETBUF_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
|
||||||
/* Note: Netconn API is always available when sockets are enabled -
|
|
||||||
* sockets are implemented on top of them */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** This netbuf has dest-addr/port set */
|
|
||||||
#define NETBUF_FLAG_DESTADDR 0x01
|
|
||||||
/** This netbuf includes a checksum */
|
|
||||||
#define NETBUF_FLAG_CHKSUM 0x02
|
|
||||||
|
|
||||||
struct netbuf {
|
|
||||||
struct pbuf *p, *ptr;
|
|
||||||
ip_addr_t addr;
|
|
||||||
u16_t port;
|
|
||||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
u8_t flags;
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
u16_t toport_chksum;
|
|
||||||
#if LWIP_NETBUF_RECVINFO
|
|
||||||
ip_addr_t toaddr;
|
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Network buffer functions: */
|
|
||||||
struct netbuf * netbuf_new (void);
|
|
||||||
void netbuf_delete (struct netbuf *buf);
|
|
||||||
void * netbuf_alloc (struct netbuf *buf, u16_t size);
|
|
||||||
void netbuf_free (struct netbuf *buf);
|
|
||||||
err_t netbuf_ref (struct netbuf *buf,
|
|
||||||
const void *dataptr, u16_t size);
|
|
||||||
void netbuf_chain (struct netbuf *head, struct netbuf *tail);
|
|
||||||
|
|
||||||
err_t netbuf_data (struct netbuf *buf,
|
|
||||||
void **dataptr, u16_t *len);
|
|
||||||
s8_t netbuf_next (struct netbuf *buf);
|
|
||||||
void netbuf_first (struct netbuf *buf);
|
|
||||||
|
|
||||||
|
|
||||||
#define netbuf_copy_partial(buf, dataptr, len, offset) \
|
|
||||||
pbuf_copy_partial((buf)->p, (dataptr), (len), (offset))
|
|
||||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
|
||||||
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
|
||||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
|
||||||
#define netbuf_fromaddr(buf) (&((buf)->addr))
|
|
||||||
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr)
|
|
||||||
#define netbuf_fromport(buf) ((buf)->port)
|
|
||||||
#if LWIP_NETBUF_RECVINFO
|
|
||||||
#define netbuf_destaddr(buf) (&((buf)->toaddr))
|
|
||||||
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr)
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
|
|
||||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
#define netbuf_destport(buf) ((buf)->toport_chksum)
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \
|
|
||||||
(buf)->toport_chksum = chksum; } while(0)
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_NETBUF_H */
|
|
|
@ -1,157 +0,0 @@
|
||||||
/*
|
|
||||||
* 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: Simon Goldschmidt
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_NETDB_H
|
|
||||||
#define LWIP_HDR_NETDB_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_DNS && LWIP_SOCKET
|
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
|
||||||
#include "lwip/sockets.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* some rarely used options */
|
|
||||||
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
|
|
||||||
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_DNS_API_DEFINE_ERRORS
|
|
||||||
#define LWIP_DNS_API_DEFINE_ERRORS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_DNS_API_DEFINE_FLAGS
|
|
||||||
#define LWIP_DNS_API_DEFINE_FLAGS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LWIP_DNS_API_DECLARE_STRUCTS
|
|
||||||
#define LWIP_DNS_API_DECLARE_STRUCTS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_DNS_API_DEFINE_ERRORS
|
|
||||||
/** Errors used by the DNS API functions, h_errno can be one of them */
|
|
||||||
#define EAI_NONAME 200
|
|
||||||
#define EAI_SERVICE 201
|
|
||||||
#define EAI_FAIL 202
|
|
||||||
#define EAI_MEMORY 203
|
|
||||||
#define EAI_FAMILY 204
|
|
||||||
|
|
||||||
#define HOST_NOT_FOUND 210
|
|
||||||
#define NO_DATA 211
|
|
||||||
#define NO_RECOVERY 212
|
|
||||||
#define TRY_AGAIN 213
|
|
||||||
#endif /* LWIP_DNS_API_DEFINE_ERRORS */
|
|
||||||
|
|
||||||
#if LWIP_DNS_API_DEFINE_FLAGS
|
|
||||||
/* input flags for struct addrinfo */
|
|
||||||
#define AI_PASSIVE 0x01
|
|
||||||
#define AI_CANONNAME 0x02
|
|
||||||
#define AI_NUMERICHOST 0x04
|
|
||||||
#define AI_NUMERICSERV 0x08
|
|
||||||
#define AI_V4MAPPED 0x10
|
|
||||||
#define AI_ALL 0x20
|
|
||||||
#define AI_ADDRCONFIG 0x40
|
|
||||||
#endif /* LWIP_DNS_API_DEFINE_FLAGS */
|
|
||||||
|
|
||||||
#if LWIP_DNS_API_DECLARE_STRUCTS
|
|
||||||
struct hostent {
|
|
||||||
char *h_name; /* Official name of the host. */
|
|
||||||
char **h_aliases; /* A pointer to an array of pointers to alternative host names,
|
|
||||||
terminated by a null pointer. */
|
|
||||||
int h_addrtype; /* Address type. */
|
|
||||||
int h_length; /* The length, in bytes, of the address. */
|
|
||||||
char **h_addr_list; /* A pointer to an array of pointers to network addresses (in
|
|
||||||
network byte order) for the host, terminated by a null pointer. */
|
|
||||||
#define h_addr h_addr_list[0] /* for backward compatibility */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct addrinfo {
|
|
||||||
int ai_flags; /* Input flags. */
|
|
||||||
int ai_family; /* Address family of socket. */
|
|
||||||
int ai_socktype; /* Socket type. */
|
|
||||||
int ai_protocol; /* Protocol of socket. */
|
|
||||||
socklen_t ai_addrlen; /* Length of socket address. */
|
|
||||||
struct sockaddr *ai_addr; /* Socket address of socket. */
|
|
||||||
char *ai_canonname; /* Canonical name of service location. */
|
|
||||||
struct addrinfo *ai_next; /* Pointer to next in list. */
|
|
||||||
};
|
|
||||||
#endif /* LWIP_DNS_API_DECLARE_STRUCTS */
|
|
||||||
|
|
||||||
#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1)
|
|
||||||
|
|
||||||
#if LWIP_DNS_API_DECLARE_H_ERRNO
|
|
||||||
/* application accessible error code set by the DNS API functions */
|
|
||||||
extern int h_errno;
|
|
||||||
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/
|
|
||||||
|
|
||||||
struct hostent *lwip_gethostbyname(const char *name);
|
|
||||||
int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
|
||||||
size_t buflen, struct hostent **result, int *h_errnop);
|
|
||||||
void lwip_freeaddrinfo(struct addrinfo *ai);
|
|
||||||
int lwip_getaddrinfo(const char *nodename,
|
|
||||||
const char *servname,
|
|
||||||
const struct addrinfo *hints,
|
|
||||||
struct addrinfo **res);
|
|
||||||
|
|
||||||
#if LWIP_COMPAT_SOCKETS
|
|
||||||
#if LWIP_COMPAT_SOCKET_ADDR == 1
|
|
||||||
/* Some libraries have problems with inet_... being macros, so please use this define
|
|
||||||
to declare normal functions */
|
|
||||||
static inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
|
|
||||||
{ return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); }
|
|
||||||
static inline struct hostent *gethostbyname(const char *name)
|
|
||||||
{ return lwip_gethostbyname(name); }
|
|
||||||
static inline void freeaddrinfo(struct addrinfo *ai)
|
|
||||||
{ lwip_freeaddrinfo(ai); }
|
|
||||||
static inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
|
|
||||||
{ return lwip_getaddrinfo(nodename, servname, hints, res); }
|
|
||||||
#else
|
|
||||||
/* By default fall back to original inet_... macros */
|
|
||||||
|
|
||||||
#define gethostbyname(name) lwip_gethostbyname(name)
|
|
||||||
#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \
|
|
||||||
lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop)
|
|
||||||
#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo)
|
|
||||||
#define getaddrinfo(nodname, servname, hints, res) \
|
|
||||||
lwip_getaddrinfo(nodname, servname, hints, res)
|
|
||||||
#endif /* LWIP_COMPAT_SOCKET_ADDR == 1 */
|
|
||||||
#endif /* LWIP_COMPAT_SOCKETS */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_NETDB_H */
|
|
|
@ -1,451 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_NETIF_H
|
|
||||||
#define LWIP_HDR_NETIF_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
|
||||||
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/stats.h"
|
|
||||||
|
|
||||||
#if LWIP_DHCP
|
|
||||||
struct dhcp;
|
|
||||||
#endif
|
|
||||||
#if LWIP_AUTOIP
|
|
||||||
struct autoip;
|
|
||||||
#endif
|
|
||||||
#if LWIP_IPV6_DHCP6
|
|
||||||
struct dhcp6;
|
|
||||||
#endif /* LWIP_IPV6_DHCP6 */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Throughout this file, IP addresses are expected to be in
|
|
||||||
* the same byte order as in IP_PCB. */
|
|
||||||
|
|
||||||
/** Must be the maximum of all used hardware address lengths
|
|
||||||
across all types of interfaces in use.
|
|
||||||
This does not have to be changed, normally. */
|
|
||||||
#ifndef NETIF_MAX_HWADDR_LEN
|
|
||||||
#define NETIF_MAX_HWADDR_LEN 6U
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Whether the network interface is 'up'. This is
|
|
||||||
* a software flag used to control whether this network
|
|
||||||
* interface is enabled and processes traffic.
|
|
||||||
* It must be set by the startup code before this netif can be used
|
|
||||||
* (also for dhcp/autoip).
|
|
||||||
*/
|
|
||||||
#define NETIF_FLAG_UP 0x01U
|
|
||||||
/** If set, the netif has broadcast capability.
|
|
||||||
* Set by the netif driver in its init function. */
|
|
||||||
#define NETIF_FLAG_BROADCAST 0x02U
|
|
||||||
/** If set, the interface has an active link
|
|
||||||
* (set by the network interface driver).
|
|
||||||
* Either set by the netif driver in its init function (if the link
|
|
||||||
* is up at that time) or at a later point once the link comes up
|
|
||||||
* (if link detection is supported by the hardware). */
|
|
||||||
#define NETIF_FLAG_LINK_UP 0x04U
|
|
||||||
/** If set, the netif is an ethernet device using ARP.
|
|
||||||
* Set by the netif driver in its init function.
|
|
||||||
* Used to check input packet types and use of DHCP. */
|
|
||||||
#define NETIF_FLAG_ETHARP 0x08U
|
|
||||||
/** If set, the netif is an ethernet device. It might not use
|
|
||||||
* ARP or TCP/IP if it is used for PPPoE only.
|
|
||||||
*/
|
|
||||||
#define NETIF_FLAG_ETHERNET 0x10U
|
|
||||||
/** If set, the netif has IGMP capability.
|
|
||||||
* Set by the netif driver in its init function. */
|
|
||||||
#define NETIF_FLAG_IGMP 0x20U
|
|
||||||
/** If set, the netif has MLD6 capability.
|
|
||||||
* Set by the netif driver in its init function. */
|
|
||||||
#define NETIF_FLAG_MLD6 0x40U
|
|
||||||
|
|
||||||
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
|
||||||
#define NETIF_CHECKSUM_GEN_IP 0x0001
|
|
||||||
#define NETIF_CHECKSUM_GEN_UDP 0x0002
|
|
||||||
#define NETIF_CHECKSUM_GEN_TCP 0x0004
|
|
||||||
#define NETIF_CHECKSUM_GEN_ICMP 0x0008
|
|
||||||
#define NETIF_CHECKSUM_GEN_ICMP6 0x0010
|
|
||||||
#define NETIF_CHECKSUM_CHECK_IP 0x0100
|
|
||||||
#define NETIF_CHECKSUM_CHECK_UDP 0x0200
|
|
||||||
#define NETIF_CHECKSUM_CHECK_TCP 0x0400
|
|
||||||
#define NETIF_CHECKSUM_CHECK_ICMP 0x0800
|
|
||||||
#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000
|
|
||||||
#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF
|
|
||||||
#define NETIF_CHECKSUM_DISABLE_ALL 0x0000
|
|
||||||
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
|
||||||
|
|
||||||
struct netif;
|
|
||||||
|
|
||||||
/** Function prototype for netif init functions. Set up flags and output/linkoutput
|
|
||||||
* callback functions in this function.
|
|
||||||
*
|
|
||||||
* @param netif The netif to initialize
|
|
||||||
*/
|
|
||||||
typedef err_t (*netif_init_fn)(struct netif *netif);
|
|
||||||
/** Function prototype for netif->input functions. This function is saved as 'input'
|
|
||||||
* callback function in the netif struct. Call it when a packet has been received.
|
|
||||||
*
|
|
||||||
* @param p The received packet, copied into a pbuf
|
|
||||||
* @param inp The netif which received the packet
|
|
||||||
*/
|
|
||||||
typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/** Function prototype for netif->output functions. Called by lwIP when a packet
|
|
||||||
* shall be sent. For ethernet netif, set this to 'etharp_output' and set
|
|
||||||
* 'linkoutput'.
|
|
||||||
*
|
|
||||||
* @param netif The netif which shall send a packet
|
|
||||||
* @param p The packet to send (p->payload points to IP header)
|
|
||||||
* @param ipaddr The IP address to which the packet shall be sent
|
|
||||||
*/
|
|
||||||
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
|
|
||||||
const ip4_addr_t *ipaddr);
|
|
||||||
#endif /* LWIP_IPV4*/
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet
|
|
||||||
* shall be sent. For ethernet netif, set this to 'ethip6_output' and set
|
|
||||||
* 'linkoutput'.
|
|
||||||
*
|
|
||||||
* @param netif The netif which shall send a packet
|
|
||||||
* @param p The packet to send (p->payload points to IP header)
|
|
||||||
* @param ipaddr The IPv6 address to which the packet shall be sent
|
|
||||||
*/
|
|
||||||
typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p,
|
|
||||||
const ip6_addr_t *ipaddr);
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/** Function prototype for netif->linkoutput functions. Only used for ethernet
|
|
||||||
* netifs. This function is called by ARP when a packet shall be sent.
|
|
||||||
*
|
|
||||||
* @param netif The netif which shall send a packet
|
|
||||||
* @param p The packet to send (raw ethernet packet)
|
|
||||||
*/
|
|
||||||
typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
|
|
||||||
/** Function prototype for netif status- or link-callback functions. */
|
|
||||||
typedef void (*netif_status_callback_fn)(struct netif *netif);
|
|
||||||
#if LWIP_IPV4 && LWIP_IGMP
|
|
||||||
/** Function prototype for netif igmp_mac_filter functions */
|
|
||||||
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
|
|
||||||
const ip4_addr_t *group, u8_t action);
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IGMP */
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
||||||
/** Function prototype for netif mld_mac_filter functions */
|
|
||||||
typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif,
|
|
||||||
const ip6_addr_t *group, u8_t action);
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
|
|
||||||
#if ESP_DHCP
|
|
||||||
/*add DHCP event processing by LiuHan*/
|
|
||||||
typedef void (*dhcp_event_fn)(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** Generic data structure used for all lwIP network interfaces.
|
|
||||||
* The following fields should be filled in by the initialization
|
|
||||||
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
|
|
||||||
struct netif {
|
|
||||||
/** pointer to next in linked list */
|
|
||||||
struct netif *next;
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/** IP address configuration in network byte order */
|
|
||||||
ip_addr_t ip_addr;
|
|
||||||
ip_addr_t netmask;
|
|
||||||
ip_addr_t gw;
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** Array of IPv6 addresses for this netif. */
|
|
||||||
ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
|
|
||||||
/** The state of each IPv6 address (Tentative, Preferred, etc).
|
|
||||||
* @see ip6_addr.h */
|
|
||||||
u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
|
|
||||||
#if ESP_LWIP
|
|
||||||
void (*ipv6_addr_cb)(struct netif* netif, u8_t ip_idex); /* callback for ipv6 addr states changed */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
/** This function is called by the network device driver
|
|
||||||
* to pass a packet up the TCP/IP stack. */
|
|
||||||
netif_input_fn input;
|
|
||||||
#if LWIP_IPV4
|
|
||||||
/** This function is called by the IP module when it wants
|
|
||||||
* to send a packet on the interface. This function typically
|
|
||||||
* first resolves the hardware address, then sends the packet. */
|
|
||||||
netif_output_fn output;
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
/** This function is called by the ARP module when it wants
|
|
||||||
* to send a packet on the interface. This function outputs
|
|
||||||
* the pbuf as-is on the link medium. */
|
|
||||||
netif_linkoutput_fn linkoutput;
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/** This function is called by the IPv6 module when it wants
|
|
||||||
* to send a packet on the interface. This function typically
|
|
||||||
* first resolves the hardware address, then sends the packet. */
|
|
||||||
netif_output_ip6_fn output_ip6;
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
|
||||||
/** This function is called when the netif state is set to up or down
|
|
||||||
*/
|
|
||||||
netif_status_callback_fn status_callback;
|
|
||||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
|
||||||
#if LWIP_NETIF_LINK_CALLBACK
|
|
||||||
/** This function is called when the netif link is set to up or down
|
|
||||||
*/
|
|
||||||
netif_status_callback_fn link_callback;
|
|
||||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
|
||||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
|
||||||
/** This function is called when the netif has been removed */
|
|
||||||
netif_status_callback_fn remove_callback;
|
|
||||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
|
||||||
/** This field can be set by the device driver and could point
|
|
||||||
* to state information for the device. */
|
|
||||||
void *state;
|
|
||||||
#if LWIP_DHCP
|
|
||||||
/** the DHCP client state information for this netif */
|
|
||||||
struct dhcp *dhcp;
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
struct udp_pcb *dhcps_pcb;
|
|
||||||
dhcp_event_fn dhcp_event;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_DHCP */
|
|
||||||
|
|
||||||
#if LWIP_AUTOIP
|
|
||||||
/** the AutoIP client state information for this netif */
|
|
||||||
struct autoip *autoip;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_IPV6_AUTOCONFIG
|
|
||||||
/** is this netif enabled for IPv6 autoconfiguration */
|
|
||||||
u8_t ip6_autoconfig_enabled;
|
|
||||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
|
||||||
|
|
||||||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
|
||||||
/** Number of Router Solicitation messages that remain to be sent. */
|
|
||||||
u8_t rs_count;
|
|
||||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
|
||||||
|
|
||||||
#if LWIP_IPV6_DHCP6
|
|
||||||
/** the DHCPv6 client state information for this netif */
|
|
||||||
struct dhcp6 *dhcp6;
|
|
||||||
#endif /* LWIP_IPV6_DHCP6 */
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HOSTNAME
|
|
||||||
/* the hostname for this netif, NULL is a valid value */
|
|
||||||
const char* hostname;
|
|
||||||
#endif /* LWIP_NETIF_HOSTNAME */
|
|
||||||
|
|
||||||
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
|
||||||
u16_t chksum_flags;
|
|
||||||
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
|
|
||||||
|
|
||||||
/** maximum transfer unit (in bytes) */
|
|
||||||
u16_t mtu;
|
|
||||||
/** number of bytes used in hwaddr */
|
|
||||||
u8_t hwaddr_len;
|
|
||||||
/** link level hardware address of this interface */
|
|
||||||
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
|
||||||
/** flags (see NETIF_FLAG_ above) */
|
|
||||||
u8_t flags;
|
|
||||||
/** descriptive abbreviation */
|
|
||||||
char name[2];
|
|
||||||
/** number of this interface */
|
|
||||||
u8_t num;
|
|
||||||
|
|
||||||
#if MIB2_STATS
|
|
||||||
/** link type (from "snmp_ifType" enum from snmp_mib2.h) */
|
|
||||||
u8_t link_type;
|
|
||||||
/** (estimate) link speed */
|
|
||||||
u32_t link_speed;
|
|
||||||
/** timestamp at last change made (up/down) */
|
|
||||||
u32_t ts;
|
|
||||||
/** counters */
|
|
||||||
struct stats_mib2_netif_ctrs mib2_counters;
|
|
||||||
#endif /* MIB2_STATS */
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IGMP
|
|
||||||
/** This function could be called to add or delete an entry in the multicast
|
|
||||||
filter table of the ethernet MAC.*/
|
|
||||||
netif_igmp_mac_filter_fn igmp_mac_filter;
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IGMP */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
||||||
/** This function could be called to add or delete an entry in the IPv6 multicast
|
|
||||||
filter table of the ethernet MAC. */
|
|
||||||
netif_mld_mac_filter_fn mld_mac_filter;
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
u8_t *addr_hint;
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
#if ENABLE_LOOPBACK
|
|
||||||
/* List of packets to be queued for ourselves. */
|
|
||||||
struct pbuf *loop_first;
|
|
||||||
struct pbuf *loop_last;
|
|
||||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
|
||||||
u16_t loop_cnt_current;
|
|
||||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
|
||||||
#endif /* ENABLE_LOOPBACK */
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
void (*l2_buffer_free_notify)(void *user_buf); /* Allows LWIP to notify driver when a L2-supplied pbuf can be freed */
|
|
||||||
ip_addr_t last_ip_addr; /* Store last non-zero ip address */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
|
||||||
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
|
|
||||||
(netif)->chksum_flags = chksumflags; } while(0)
|
|
||||||
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0))
|
|
||||||
#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
|
||||||
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags)
|
|
||||||
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
|
|
||||||
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
|
||||||
|
|
||||||
/** The list of network interfaces. */
|
|
||||||
extern struct netif *netif_list;
|
|
||||||
/** The default network interface. */
|
|
||||||
extern struct netif *netif_default;
|
|
||||||
|
|
||||||
void netif_init(void);
|
|
||||||
|
|
||||||
struct netif *netif_add(struct netif *netif,
|
|
||||||
#if LWIP_IPV4
|
|
||||||
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
void *state, netif_init_fn init, netif_input_fn input);
|
|
||||||
#if LWIP_IPV4
|
|
||||||
void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
|
|
||||||
const ip4_addr_t *gw);
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
void netif_remove(struct netif * netif);
|
|
||||||
|
|
||||||
/* Returns a network interface given its name. The name is of the form
|
|
||||||
"et0", where the first two letters are the "name" field in the
|
|
||||||
netif structure, and the digit is in the num field in the same
|
|
||||||
structure. */
|
|
||||||
struct netif *netif_find(const char *name);
|
|
||||||
|
|
||||||
void netif_set_default(struct netif *netif);
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr);
|
|
||||||
void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask);
|
|
||||||
void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
|
|
||||||
#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr)))
|
|
||||||
#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask)))
|
|
||||||
#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw)))
|
|
||||||
#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr))
|
|
||||||
#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw))
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
void netif_set_up(struct netif *netif);
|
|
||||||
void netif_set_down(struct netif *netif);
|
|
||||||
/** Ask if an interface is up */
|
|
||||||
#define netif_is_up(netif) ( ((netif) && ((netif)->flags & NETIF_FLAG_UP)) ? (u8_t)1 : (u8_t)0)
|
|
||||||
|
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
|
||||||
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
|
|
||||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
|
||||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
|
||||||
void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback);
|
|
||||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
|
||||||
|
|
||||||
void netif_set_link_up(struct netif *netif);
|
|
||||||
void netif_set_link_down(struct netif *netif);
|
|
||||||
/** Ask if a link is up */
|
|
||||||
#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
|
|
||||||
|
|
||||||
#if LWIP_NETIF_LINK_CALLBACK
|
|
||||||
void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback);
|
|
||||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HOSTNAME
|
|
||||||
#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0)
|
|
||||||
#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL)
|
|
||||||
#endif /* LWIP_NETIF_HOSTNAME */
|
|
||||||
|
|
||||||
#if LWIP_IGMP
|
|
||||||
#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
|
|
||||||
#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL)
|
|
||||||
#endif /* LWIP_IGMP */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
||||||
#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0)
|
|
||||||
#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL)
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
#if ENABLE_LOOPBACK
|
|
||||||
err_t netif_loop_output(struct netif *netif, struct pbuf *p);
|
|
||||||
void netif_poll(struct netif *netif);
|
|
||||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
|
||||||
void netif_poll_all(void);
|
|
||||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
|
||||||
#endif /* ENABLE_LOOPBACK */
|
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i])))
|
|
||||||
#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i])))
|
|
||||||
#define netif_ip6_addr_set(netif, i, addr6) do { ip6_addr_set(ip_2_ip6(&((netif)->ip6_addr[i])), addr6); IP_SET_TYPE_VAL((netif)->ip6_addr[i], IPADDR_TYPE_V6); } while(0)
|
|
||||||
#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i])
|
|
||||||
#define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[i] = (state))
|
|
||||||
s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr);
|
|
||||||
void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit);
|
|
||||||
err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx);
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint))
|
|
||||||
#else /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
#define NETIF_SET_HWADDRHINT(netif, hint)
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_NETIF_H */
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_NETIFAPI_H
|
|
||||||
#define LWIP_HDR_NETIFAPI_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/dhcp.h"
|
|
||||||
#include "lwip/autoip.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
#define NETIFAPI_IPADDR_DEF(type, m) type m
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
#define NETIFAPI_IPADDR_DEF(type, m) const type * m
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
|
|
||||||
typedef void (*netifapi_void_fn)(struct netif *netif);
|
|
||||||
typedef err_t (*netifapi_errt_fn)(struct netif *netif);
|
|
||||||
|
|
||||||
struct netifapi_msg {
|
|
||||||
struct tcpip_api_call call;
|
|
||||||
struct netif *netif;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
#if LWIP_IPV4
|
|
||||||
NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr);
|
|
||||||
NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask);
|
|
||||||
NETIFAPI_IPADDR_DEF(ip4_addr_t, gw);
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
void *state;
|
|
||||||
netif_init_fn init;
|
|
||||||
netif_input_fn input;
|
|
||||||
} add;
|
|
||||||
struct {
|
|
||||||
netifapi_void_fn voidfunc;
|
|
||||||
netifapi_errt_fn errtfunc;
|
|
||||||
} common;
|
|
||||||
} msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* API for application */
|
|
||||||
err_t netifapi_netif_add(struct netif *netif,
|
|
||||||
#if LWIP_IPV4
|
|
||||||
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
void *state, netif_init_fn init, netif_input_fn input);
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr,
|
|
||||||
const ip4_addr_t *netmask, const ip4_addr_t *gw);
|
|
||||||
#endif /* LWIP_IPV4*/
|
|
||||||
|
|
||||||
err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
|
||||||
netifapi_errt_fn errtfunc);
|
|
||||||
|
|
||||||
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
|
|
||||||
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
|
|
||||||
#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL)
|
|
||||||
#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL)
|
|
||||||
#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start)
|
|
||||||
#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL)
|
|
||||||
#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL)
|
|
||||||
#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew)
|
|
||||||
#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release)
|
|
||||||
#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start)
|
|
||||||
#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_NETIF_API */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_NETIFAPI_H */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,234 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_PBUF_H
|
|
||||||
#define LWIP_HDR_PBUF_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type
|
|
||||||
* but they are allocated by external code (initialised by calling
|
|
||||||
* pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they
|
|
||||||
* are freed by calling pbuf_custom->custom_free_function().
|
|
||||||
* Currently, the pbuf_custom code is only needed for one specific configuration
|
|
||||||
* of IP_FRAG, unless required by external driver/application code. */
|
|
||||||
#ifndef LWIP_SUPPORT_CUSTOM_PBUF
|
|
||||||
#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* @todo: We need a mechanism to prevent wasting memory in every pbuf
|
|
||||||
(TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */
|
|
||||||
|
|
||||||
#define PBUF_TRANSPORT_HLEN 20
|
|
||||||
#if LWIP_IPV6
|
|
||||||
#define PBUF_IP_HLEN 40
|
|
||||||
#else
|
|
||||||
#define PBUF_IP_HLEN 20
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PBUF_TRANSPORT,
|
|
||||||
PBUF_IP,
|
|
||||||
PBUF_LINK,
|
|
||||||
PBUF_RAW_TX,
|
|
||||||
PBUF_RAW
|
|
||||||
} pbuf_layer;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
/** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload
|
|
||||||
are allocated in one piece of contiguous memory (so the first payload byte
|
|
||||||
can be calculated from struct pbuf)
|
|
||||||
pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might
|
|
||||||
change in future versions) */
|
|
||||||
PBUF_RAM,
|
|
||||||
/** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in
|
|
||||||
totally different memory areas. Since it points to ROM, payload does not
|
|
||||||
have to be copied when queued for transmission. */
|
|
||||||
PBUF_ROM,
|
|
||||||
/** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change
|
|
||||||
so it has to be duplicated when queued before transmitting, depending on
|
|
||||||
who has a 'ref' to it. */
|
|
||||||
PBUF_REF,
|
|
||||||
/** pbuf payload refers to RAM. This one comes from a pool and should be used
|
|
||||||
for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct
|
|
||||||
pbuf and its payload are allocated in one piece of contiguous memory (so
|
|
||||||
the first payload byte can be calculated from struct pbuf) */
|
|
||||||
PBUF_POOL
|
|
||||||
} pbuf_type;
|
|
||||||
|
|
||||||
|
|
||||||
/** indicates this packet's data should be immediately passed to the application */
|
|
||||||
#define PBUF_FLAG_PUSH 0x01U
|
|
||||||
/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function()
|
|
||||||
when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */
|
|
||||||
#define PBUF_FLAG_IS_CUSTOM 0x02U
|
|
||||||
/** indicates this pbuf is UDP multicast to be looped back */
|
|
||||||
#define PBUF_FLAG_MCASTLOOP 0x04U
|
|
||||||
/** indicates this pbuf was received as link-level broadcast */
|
|
||||||
#define PBUF_FLAG_LLBCAST 0x08U
|
|
||||||
/** indicates this pbuf was received as link-level multicast */
|
|
||||||
#define PBUF_FLAG_LLMCAST 0x10U
|
|
||||||
/** indicates this pbuf includes a TCP FIN flag */
|
|
||||||
#define PBUF_FLAG_TCP_FIN 0x20U
|
|
||||||
|
|
||||||
struct pbuf {
|
|
||||||
/** next pbuf in singly linked pbuf chain */
|
|
||||||
struct pbuf *next;
|
|
||||||
|
|
||||||
/** pointer to the actual data in the buffer */
|
|
||||||
void *payload;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* total length of this buffer and all next buffers in chain
|
|
||||||
* belonging to the same packet.
|
|
||||||
*
|
|
||||||
* For non-queue packet chains this is the invariant:
|
|
||||||
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
|
|
||||||
*/
|
|
||||||
u16_t tot_len;
|
|
||||||
|
|
||||||
/** length of this buffer */
|
|
||||||
u16_t len;
|
|
||||||
|
|
||||||
/** pbuf_type as u8_t instead of enum to save space */
|
|
||||||
u8_t /*pbuf_type*/ type;
|
|
||||||
|
|
||||||
/** misc flags */
|
|
||||||
u8_t flags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the reference count always equals the number of pointers
|
|
||||||
* that refer to this pbuf. This can be pointers from an application,
|
|
||||||
* the stack itself, or pbuf->next pointers from a chain.
|
|
||||||
*/
|
|
||||||
u16_t ref;
|
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
struct netif *l2_owner;
|
|
||||||
void *l2_buf;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** Helper struct for const-correctness only.
|
|
||||||
* The only meaning of this one is to provide a const payload pointer
|
|
||||||
* for PBUF_ROM type.
|
|
||||||
*/
|
|
||||||
struct pbuf_rom {
|
|
||||||
/** next pbuf in singly linked pbuf chain */
|
|
||||||
struct pbuf *next;
|
|
||||||
|
|
||||||
/** pointer to the actual data in the buffer */
|
|
||||||
const void *payload;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
|
||||||
/** Prototype for a function to free a custom pbuf */
|
|
||||||
typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
|
|
||||||
|
|
||||||
/** A custom pbuf: like a pbuf, but following a function pointer to free it. */
|
|
||||||
struct pbuf_custom {
|
|
||||||
/** The actual pbuf */
|
|
||||||
struct pbuf pbuf;
|
|
||||||
/** This function is called when pbuf_free deallocates this pbuf(_custom) */
|
|
||||||
pbuf_free_custom_fn custom_free_function;
|
|
||||||
};
|
|
||||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
|
||||||
|
|
||||||
|
|
||||||
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
|
|
||||||
#ifndef PBUF_POOL_FREE_OOSEQ
|
|
||||||
#define PBUF_POOL_FREE_OOSEQ 1
|
|
||||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
|
||||||
#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ
|
|
||||||
extern volatile u8_t pbuf_free_ooseq_pending;
|
|
||||||
void pbuf_free_ooseq(void);
|
|
||||||
/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
|
|
||||||
at regular intervals from main level to check if ooseq pbufs need to be
|
|
||||||
freed! */
|
|
||||||
#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \
|
|
||||||
/* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \
|
|
||||||
ooseq queued pbufs now */ \
|
|
||||||
pbuf_free_ooseq(); }}while(0)
|
|
||||||
#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */
|
|
||||||
/* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */
|
|
||||||
#define PBUF_CHECK_FREE_OOSEQ()
|
|
||||||
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/
|
|
||||||
|
|
||||||
/* Initializes the pbuf module. This call is empty for now, but may not be in future. */
|
|
||||||
#define pbuf_init()
|
|
||||||
|
|
||||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
|
|
||||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
|
||||||
struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type,
|
|
||||||
struct pbuf_custom *p, void *payload_mem,
|
|
||||||
u16_t payload_mem_len);
|
|
||||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
|
||||||
void pbuf_realloc(struct pbuf *p, u16_t size);
|
|
||||||
u8_t pbuf_header(struct pbuf *p, s16_t header_size);
|
|
||||||
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size);
|
|
||||||
void pbuf_ref(struct pbuf *p);
|
|
||||||
u8_t pbuf_free(struct pbuf *p);
|
|
||||||
u8_t pbuf_clen(struct pbuf *p);
|
|
||||||
void pbuf_cat(struct pbuf *head, struct pbuf *tail);
|
|
||||||
void pbuf_chain(struct pbuf *head, struct pbuf *tail);
|
|
||||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
|
||||||
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
|
|
||||||
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
|
||||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
|
||||||
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset);
|
|
||||||
struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset);
|
|
||||||
struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
|
||||||
err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
|
||||||
u16_t len, u16_t *chksum);
|
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
|
||||||
#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
|
|
||||||
void pbuf_split_64k(struct pbuf *p, struct pbuf **rest);
|
|
||||||
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
|
|
||||||
|
|
||||||
u8_t pbuf_get_at(struct pbuf* p, u16_t offset);
|
|
||||||
void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data);
|
|
||||||
u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n);
|
|
||||||
u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset);
|
|
||||||
u16_t pbuf_strstr(struct pbuf* p, const char* substr);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_PBUF_H */
|
|
|
@ -1,148 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LWIP_PPPAPI_H__
|
|
||||||
#define __LWIP_PPPAPI_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
|
||||||
#include "netif/ppp/ppp.h"
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
#include "netif/ppp/pppos.h"
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct pppapi_msg_msg {
|
|
||||||
ppp_pcb *ppp;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
u8_t authtype;
|
|
||||||
const char *user;
|
|
||||||
const char *passwd;
|
|
||||||
} setauth;
|
|
||||||
#if PPP_NOTIFY_PHASE
|
|
||||||
struct {
|
|
||||||
ppp_notify_phase_cb_fn notify_phase_cb;
|
|
||||||
} setnotifyphasecb;
|
|
||||||
#endif /* PPP_NOTIFY_PHASE */
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
struct {
|
|
||||||
struct netif *pppif;
|
|
||||||
pppos_output_cb_fn output_cb;
|
|
||||||
ppp_link_status_cb_fn link_status_cb;
|
|
||||||
void *ctx_cb;
|
|
||||||
} serialcreate;
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
#if PPPOE_SUPPORT
|
|
||||||
struct {
|
|
||||||
struct netif *pppif;
|
|
||||||
struct netif *ethif;
|
|
||||||
const char *service_name;
|
|
||||||
const char *concentrator_name;
|
|
||||||
ppp_link_status_cb_fn link_status_cb;
|
|
||||||
void *ctx_cb;
|
|
||||||
} ethernetcreate;
|
|
||||||
#endif /* PPPOE_SUPPORT */
|
|
||||||
#if PPPOL2TP_SUPPORT
|
|
||||||
struct {
|
|
||||||
struct netif *pppif;
|
|
||||||
struct netif *netif;
|
|
||||||
ip_addr_t *ipaddr;
|
|
||||||
u16_t port;
|
|
||||||
#if PPPOL2TP_AUTH_SUPPORT
|
|
||||||
const u8_t *secret;
|
|
||||||
u8_t secret_len;
|
|
||||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
|
||||||
ppp_link_status_cb_fn link_status_cb;
|
|
||||||
void *ctx_cb;
|
|
||||||
} l2tpcreate;
|
|
||||||
#endif /* PPPOL2TP_SUPPORT */
|
|
||||||
struct {
|
|
||||||
u16_t holdoff;
|
|
||||||
} connect;
|
|
||||||
#if PPP_SERVER
|
|
||||||
struct {
|
|
||||||
struct ppp_addrs *addrs;
|
|
||||||
} listen;
|
|
||||||
#endif /* PPP_SERVER */
|
|
||||||
struct {
|
|
||||||
u8_t nocarrier;
|
|
||||||
} close;
|
|
||||||
struct {
|
|
||||||
u8_t cmd;
|
|
||||||
void *arg;
|
|
||||||
} ioctl;
|
|
||||||
} msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pppapi_msg {
|
|
||||||
struct tcpip_api_call call;
|
|
||||||
struct pppapi_msg_msg msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* API for application */
|
|
||||||
void pppapi_set_default(ppp_pcb *pcb);
|
|
||||||
void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd);
|
|
||||||
#if PPP_NOTIFY_PHASE
|
|
||||||
void pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb);
|
|
||||||
#endif /* PPP_NOTIFY_PHASE */
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
#if PPPOE_SUPPORT
|
|
||||||
ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name,
|
|
||||||
const char *concentrator_name, ppp_link_status_cb_fn link_status_cb,
|
|
||||||
void *ctx_cb);
|
|
||||||
#endif /* PPPOE_SUPPORT */
|
|
||||||
#if PPPOL2TP_SUPPORT
|
|
||||||
ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port,
|
|
||||||
const u8_t *secret, u8_t secret_len,
|
|
||||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
|
||||||
#endif /* PPPOL2TP_SUPPORT */
|
|
||||||
err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff);
|
|
||||||
#if PPP_SERVER
|
|
||||||
err_t pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs);
|
|
||||||
#endif /* PPP_SERVER */
|
|
||||||
err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier);
|
|
||||||
err_t pppapi_free(ppp_pcb *pcb);
|
|
||||||
err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_PPP_API */
|
|
||||||
|
|
||||||
#endif /* __LWIP_PPPAPI_H__ */
|
|
|
@ -1,259 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_API_MSG_H
|
|
||||||
#define LWIP_HDR_API_MSG_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
|
||||||
/* Note: Netconn API is always available when sockets are enabled -
|
|
||||||
* sockets are implemented on top of them */
|
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/igmp.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
#define API_MSG_M_DEF(m) m
|
|
||||||
#define API_MSG_M_DEF_C(t, m) t m
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
#define API_MSG_M_DEF_SEM(m) *m
|
|
||||||
#else
|
|
||||||
#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m)
|
|
||||||
#endif
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
#define API_MSG_M_DEF(m) *m
|
|
||||||
#define API_MSG_M_DEF_C(t, m) const t * m
|
|
||||||
#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m)
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
|
|
||||||
/* For the netconn API, these values are use as a bitmask! */
|
|
||||||
#define NETCONN_SHUT_RD 1
|
|
||||||
#define NETCONN_SHUT_WR 2
|
|
||||||
#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
|
|
||||||
|
|
||||||
/* IP addresses and port numbers are expected to be in
|
|
||||||
* the same byte order as in the corresponding pcb.
|
|
||||||
*/
|
|
||||||
/** This struct includes everything that is necessary to execute a function
|
|
||||||
for a netconn in another thread context (mainly used to process netconns
|
|
||||||
in the tcpip_thread context to be thread safe). */
|
|
||||||
struct api_msg_msg {
|
|
||||||
/** The netconn which to process - always needed: it includes the semaphore
|
|
||||||
which is used to block the application thread until the function finished. */
|
|
||||||
struct netconn *conn;
|
|
||||||
/** The return value of the function executed in tcpip_thread. */
|
|
||||||
err_t err;
|
|
||||||
/** Depending on the executed function, one of these union members is used */
|
|
||||||
union {
|
|
||||||
/** used for lwip_netconn_do_send */
|
|
||||||
struct netbuf *b;
|
|
||||||
/** used for lwip_netconn_do_newconn */
|
|
||||||
struct {
|
|
||||||
u8_t proto;
|
|
||||||
} n;
|
|
||||||
/** used for lwip_netconn_do_bind and lwip_netconn_do_connect */
|
|
||||||
struct {
|
|
||||||
API_MSG_M_DEF_C(ip_addr_t, ipaddr);
|
|
||||||
u16_t port;
|
|
||||||
} bc;
|
|
||||||
/** used for lwip_netconn_do_getaddr */
|
|
||||||
struct {
|
|
||||||
ip_addr_t API_MSG_M_DEF(ipaddr);
|
|
||||||
u16_t API_MSG_M_DEF(port);
|
|
||||||
u8_t local;
|
|
||||||
} ad;
|
|
||||||
/** used for lwip_netconn_do_write */
|
|
||||||
struct {
|
|
||||||
const void *dataptr;
|
|
||||||
size_t len;
|
|
||||||
u8_t apiflags;
|
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
u32_t time_started;
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO */
|
|
||||||
} w;
|
|
||||||
/** used for lwip_netconn_do_recv */
|
|
||||||
struct {
|
|
||||||
u32_t len;
|
|
||||||
} r;
|
|
||||||
#if LWIP_TCP
|
|
||||||
/** used for lwip_netconn_do_close (/shutdown) */
|
|
||||||
struct {
|
|
||||||
u8_t shut;
|
|
||||||
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
|
|
||||||
u32_t time_started;
|
|
||||||
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
u8_t polls_left;
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
|
||||||
} sd;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
|
||||||
/** used for lwip_netconn_do_join_leave_group */
|
|
||||||
struct {
|
|
||||||
API_MSG_M_DEF_C(ip_addr_t, multiaddr);
|
|
||||||
API_MSG_M_DEF_C(ip_addr_t, netif_addr);
|
|
||||||
enum netconn_igmp join_or_leave;
|
|
||||||
} jl;
|
|
||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
|
||||||
struct {
|
|
||||||
u8_t backlog;
|
|
||||||
} lb;
|
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
|
||||||
} msg;
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_sem_t* op_completed_sem;
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem)
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed)
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
|
|
||||||
|
|
||||||
/** This struct contains a function to execute in another thread context and
|
|
||||||
a struct api_msg_msg that serves as an argument for this function.
|
|
||||||
This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */
|
|
||||||
struct api_msg {
|
|
||||||
/** function to execute in tcpip_thread context */
|
|
||||||
void (* function)(void *msg);
|
|
||||||
/** arguments for this function */
|
|
||||||
struct api_msg_msg msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_DNS
|
|
||||||
/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn,
|
|
||||||
it has its own struct (to avoid struct api_msg getting bigger than necessary).
|
|
||||||
lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg
|
|
||||||
(see netconn_gethostbyname). */
|
|
||||||
struct dns_api_msg {
|
|
||||||
/** Hostname to query or dotted IP address string */
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
char name[DNS_MAX_NAME_LENGTH];
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
const char *name;
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
/** The resolved address is stored here */
|
|
||||||
ip_addr_t API_MSG_M_DEF(addr);
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
/** Type of resolve call */
|
|
||||||
u8_t dns_addrtype;
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
/** This semaphore is posted when the name is resolved, the application thread
|
|
||||||
should wait on it. */
|
|
||||||
sys_sem_t API_MSG_M_DEF_SEM(sem);
|
|
||||||
/** Errors are given back here */
|
|
||||||
err_t API_MSG_M_DEF(err);
|
|
||||||
};
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
#if ESP_THREAD_SAFE
|
|
||||||
#define LWIP_NETCONN_THREAD_SEM_GET() sys_thread_sem_get()
|
|
||||||
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_thread_sem_init()
|
|
||||||
#define LWIP_NETCONN_THREAD_SEM_FREE() sys_thread_sem_deinit()
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
#define TCIP_APIMSG_SET_ERR(m, e) (m)->msg.err = e /* catch functions that don't set err */
|
|
||||||
#else
|
|
||||||
#define TCIP_APIMSG_SET_ERR(m, e)
|
|
||||||
#endif
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
#define TCPIP_APIMSG_SET_SEM(m) ((m)->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET())
|
|
||||||
#else
|
|
||||||
#define TCPIP_APIMSG_SET_SEM(m)
|
|
||||||
#endif
|
|
||||||
#define TCPIP_APIMSG_NOERR(m,f) do { \
|
|
||||||
TCIP_APIMSG_SET_ERR(m, ERR_VAL); \
|
|
||||||
TCPIP_APIMSG_SET_SEM(m); \
|
|
||||||
LOCK_TCPIP_CORE(); \
|
|
||||||
f(&((m)->msg)); \
|
|
||||||
UNLOCK_TCPIP_CORE(); \
|
|
||||||
} while(0)
|
|
||||||
#define TCPIP_APIMSG(m,f,e) do { \
|
|
||||||
TCPIP_APIMSG_NOERR(m,f); \
|
|
||||||
(e) = (m)->msg.err; \
|
|
||||||
} while(0)
|
|
||||||
#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err)
|
|
||||||
#else /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
#define TCPIP_APIMSG_NOERR(m,f) do { (m)->function = f; tcpip_apimsg(m); } while(0)
|
|
||||||
#define TCPIP_APIMSG(m,f,e) do { (m)->function = f; (e) = tcpip_apimsg(m); } while(0)
|
|
||||||
#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0)
|
|
||||||
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
void lwip_netconn_do_newconn (void *m);
|
|
||||||
void lwip_netconn_do_delconn (void *m);
|
|
||||||
void lwip_netconn_do_bind (void *m);
|
|
||||||
void lwip_netconn_do_connect (void *m);
|
|
||||||
void lwip_netconn_do_disconnect (void *m);
|
|
||||||
void lwip_netconn_do_listen (void *m);
|
|
||||||
void lwip_netconn_do_send (void *m);
|
|
||||||
void lwip_netconn_do_recv (void *m);
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
|
||||||
void lwip_netconn_do_accepted (void *m);
|
|
||||||
#endif
|
|
||||||
void lwip_netconn_do_write (void *m);
|
|
||||||
void lwip_netconn_do_getaddr (void *m);
|
|
||||||
void lwip_netconn_do_close (void *m);
|
|
||||||
void lwip_netconn_do_shutdown (void *m);
|
|
||||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
|
||||||
void lwip_netconn_do_join_leave_group(void *m);
|
|
||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
|
||||||
|
|
||||||
#if LWIP_DNS
|
|
||||||
void lwip_netconn_do_gethostbyname(void *arg);
|
|
||||||
#endif /* LWIP_DNS */
|
|
||||||
|
|
||||||
struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback);
|
|
||||||
void netconn_free(struct netconn *conn);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_API_MSG_H */
|
|
|
@ -1,173 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_MEMP_PRIV_H
|
|
||||||
#define LWIP_HDR_MEMP_PRIV_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning
|
|
||||||
* and at the end of each element, initialize them as 0xcd and check
|
|
||||||
* them later. */
|
|
||||||
/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free,
|
|
||||||
* every single element in each pool is checked!
|
|
||||||
* This is VERY SLOW but also very helpful. */
|
|
||||||
/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in
|
|
||||||
* lwipopts.h to change the amount reserved for checking. */
|
|
||||||
#ifndef MEMP_SANITY_REGION_BEFORE
|
|
||||||
#define MEMP_SANITY_REGION_BEFORE 16
|
|
||||||
#endif /* MEMP_SANITY_REGION_BEFORE*/
|
|
||||||
#if MEMP_SANITY_REGION_BEFORE > 0
|
|
||||||
#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE)
|
|
||||||
#else
|
|
||||||
#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0
|
|
||||||
#endif /* MEMP_SANITY_REGION_BEFORE*/
|
|
||||||
#ifndef MEMP_SANITY_REGION_AFTER
|
|
||||||
#define MEMP_SANITY_REGION_AFTER 16
|
|
||||||
#endif /* MEMP_SANITY_REGION_AFTER*/
|
|
||||||
#if MEMP_SANITY_REGION_AFTER > 0
|
|
||||||
#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER)
|
|
||||||
#else
|
|
||||||
#define MEMP_SANITY_REGION_AFTER_ALIGNED 0
|
|
||||||
#endif /* MEMP_SANITY_REGION_AFTER*/
|
|
||||||
|
|
||||||
/* MEMP_SIZE: save space for struct memp and for sanity check */
|
|
||||||
#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED)
|
|
||||||
#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED)
|
|
||||||
|
|
||||||
#else /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
/* No sanity checks
|
|
||||||
* We don't need to preserve the struct memp while not allocated, so we
|
|
||||||
* can save a little space and set MEMP_SIZE to 0.
|
|
||||||
*/
|
|
||||||
#define MEMP_SIZE 0
|
|
||||||
#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
|
|
||||||
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
struct memp {
|
|
||||||
struct memp *next;
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
const char *file;
|
|
||||||
int line;
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
};
|
|
||||||
|
|
||||||
#if MEM_USE_POOLS
|
|
||||||
/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */
|
|
||||||
typedef enum {
|
|
||||||
/* Get the first (via:
|
|
||||||
MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/
|
|
||||||
MEMP_POOL_HELPER_FIRST = ((u8_t)
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc)
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_START 1
|
|
||||||
#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_END
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
) ,
|
|
||||||
/* Get the last (via:
|
|
||||||
MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */
|
|
||||||
MEMP_POOL_HELPER_LAST = ((u8_t)
|
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc)
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_START
|
|
||||||
#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size *
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_END 1
|
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
)
|
|
||||||
} memp_pool_helper_t;
|
|
||||||
|
|
||||||
/* The actual start and stop values are here (cast them over)
|
|
||||||
We use this helper type and these defines so we can avoid using const memp_t values */
|
|
||||||
#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST)
|
|
||||||
#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST)
|
|
||||||
#endif /* MEM_USE_POOLS */
|
|
||||||
|
|
||||||
struct memp_desc {
|
|
||||||
/** Element size */
|
|
||||||
u16_t size;
|
|
||||||
|
|
||||||
#if !MEMP_MEM_MALLOC
|
|
||||||
/** Number of elements */
|
|
||||||
u16_t num;
|
|
||||||
|
|
||||||
#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK
|
|
||||||
/** Textual description */
|
|
||||||
const char *desc;
|
|
||||||
#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK */
|
|
||||||
|
|
||||||
/** Base */
|
|
||||||
u8_t *base;
|
|
||||||
|
|
||||||
/** First free element of each pool. Elements form a linked list. */
|
|
||||||
struct memp **tab;
|
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
|
||||||
};
|
|
||||||
|
|
||||||
#if (ESP_STATS_MEM == 1)
|
|
||||||
extern uint32_t g_lwip_mem_cnt[MEMP_MAX][2];
|
|
||||||
#define ESP_CNT_MEM_MALLOC_INC(type) g_lwip_mem_cnt[type][0]++
|
|
||||||
#define ESP_CNT_MEM_FREE_INC(type) g_lwip_mem_cnt[type][1]++
|
|
||||||
#else
|
|
||||||
#define ESP_CNT_MEM_MALLOC_INC(type)
|
|
||||||
#define ESP_CNT_MEM_FREE_INC(type)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc),
|
|
||||||
#else
|
|
||||||
#define DECLARE_LWIP_MEMPOOL_DESC(desc)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void memp_init_pool(const struct memp_desc *desc);
|
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK
|
|
||||||
void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line);
|
|
||||||
#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
void *memp_malloc_pool(const struct memp_desc *desc);
|
|
||||||
#endif
|
|
||||||
void memp_free_pool(const struct memp_desc* desc, void *mem);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_MEMP_PRIV_H */
|
|
|
@ -1,151 +0,0 @@
|
||||||
/*
|
|
||||||
* SETUP: Make sure we define everything we will need.
|
|
||||||
*
|
|
||||||
* We have create three types of pools:
|
|
||||||
* 1) MEMPOOL - standard pools
|
|
||||||
* 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c
|
|
||||||
* 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct
|
|
||||||
*
|
|
||||||
* If the include'r doesn't require any special treatment of each of the types
|
|
||||||
* above, then will declare #2 & #3 to be just standard mempools.
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_MALLOC_MEMPOOL
|
|
||||||
/* This treats "malloc pools" just like any other pool.
|
|
||||||
The pools are a little bigger to provide 'size' as the amount of user data. */
|
|
||||||
#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size)
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_START
|
|
||||||
#define LWIP_MALLOC_MEMPOOL_END
|
|
||||||
#endif /* LWIP_MALLOC_MEMPOOL */
|
|
||||||
|
|
||||||
#ifndef LWIP_PBUF_MEMPOOL
|
|
||||||
/* This treats "pbuf pools" just like any other pool.
|
|
||||||
* Allocates buffers for a pbuf struct AND a payload size */
|
|
||||||
#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc)
|
|
||||||
#endif /* LWIP_PBUF_MEMPOOL */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A list of internal pools used by LWIP.
|
|
||||||
*
|
|
||||||
* LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description)
|
|
||||||
* creates a pool name MEMP_pool_name. description is used in stats.c
|
|
||||||
*/
|
|
||||||
#if LWIP_RAW
|
|
||||||
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
|
|
||||||
#endif /* LWIP_RAW */
|
|
||||||
|
|
||||||
#if LWIP_UDP
|
|
||||||
LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB")
|
|
||||||
#endif /* LWIP_UDP */
|
|
||||||
|
|
||||||
#if LWIP_TCP
|
|
||||||
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
|
|
||||||
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
|
|
||||||
LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && IP_REASSEMBLY
|
|
||||||
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
|
|
||||||
#endif /* LWIP_IPV4 && IP_REASSEMBLY */
|
|
||||||
#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)
|
|
||||||
LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
|
|
||||||
#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
|
||||||
|
|
||||||
#if LWIP_NETCONN || LWIP_SOCKET
|
|
||||||
LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF")
|
|
||||||
LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN")
|
|
||||||
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
|
||||||
|
|
||||||
#if NO_SYS==0
|
|
||||||
LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API")
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG")
|
|
||||||
#if LWIP_DNS
|
|
||||||
LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG")
|
|
||||||
#endif
|
|
||||||
#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA")
|
|
||||||
#endif
|
|
||||||
#if LWIP_NETIF_API
|
|
||||||
LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG")
|
|
||||||
#endif
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
|
|
||||||
LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT")
|
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
|
|
||||||
#endif /* NO_SYS==0 */
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING
|
|
||||||
LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE")
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */
|
|
||||||
|
|
||||||
#if LWIP_IGMP
|
|
||||||
LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP")
|
|
||||||
#endif /* LWIP_IGMP */
|
|
||||||
|
|
||||||
#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */
|
|
||||||
LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT")
|
|
||||||
#endif /* LWIP_TIMERS */
|
|
||||||
|
|
||||||
#if LWIP_DNS && LWIP_SOCKET
|
|
||||||
LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB")
|
|
||||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
|
||||||
#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
|
||||||
LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST")
|
|
||||||
#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
|
||||||
|
|
||||||
#if PPP_SUPPORT
|
|
||||||
LWIP_MEMPOOL(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB")
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
LWIP_MEMPOOL(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB")
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
#if PPPOE_SUPPORT
|
|
||||||
LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
|
|
||||||
#endif /* PPPOE_SUPPORT */
|
|
||||||
#if PPPOL2TP_SUPPORT
|
|
||||||
LWIP_MEMPOOL(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB")
|
|
||||||
#endif /* PPPOL2TP_SUPPORT */
|
|
||||||
#endif /* PPP_SUPPORT */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_ND6_QUEUEING
|
|
||||||
LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE")
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_REASS
|
|
||||||
LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA")
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
||||||
LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP")
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A list of pools of pbuf's used by LWIP.
|
|
||||||
*
|
|
||||||
* LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description)
|
|
||||||
* creates a pool name MEMP_pool_name. description is used in stats.c
|
|
||||||
* This allocates enough space for the pbuf struct and a payload.
|
|
||||||
* (Example: pbuf_payload_size=0 allocates only size for the struct)
|
|
||||||
*/
|
|
||||||
LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM")
|
|
||||||
LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL")
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allow for user-defined pools; this must be explicitly set in lwipopts.h
|
|
||||||
* since the default is to NOT look for lwippools.h
|
|
||||||
*/
|
|
||||||
#if MEMP_USE_CUSTOM_POOLS
|
|
||||||
#include "lwippools.h"
|
|
||||||
#endif /* MEMP_USE_CUSTOM_POOLS */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later
|
|
||||||
* (#undef is ignored for something that is not defined)
|
|
||||||
*/
|
|
||||||
#undef LWIP_MEMPOOL
|
|
||||||
#undef LWIP_MALLOC_MEMPOOL
|
|
||||||
#undef LWIP_MALLOC_MEMPOOL_START
|
|
||||||
#undef LWIP_MALLOC_MEMPOOL_END
|
|
||||||
#undef LWIP_PBUF_MEMPOOL
|
|
|
@ -1,545 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_TCP_IMPL_H
|
|
||||||
#define LWIP_HDR_TCP_IMPL_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/tcp.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/icmp.h"
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/ip6.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Functions for interfacing with TCP: */
|
|
||||||
|
|
||||||
/* Lower layer interface to TCP: */
|
|
||||||
void tcp_init (void); /* Initialize this module. */
|
|
||||||
void tcp_tmr (void); /* Must be called every
|
|
||||||
TCP_TMR_INTERVAL
|
|
||||||
ms. (Typically 250 ms). */
|
|
||||||
/* It is also possible to call these two functions at the right
|
|
||||||
intervals (instead of calling tcp_tmr()). */
|
|
||||||
void tcp_slowtmr (void);
|
|
||||||
void tcp_fasttmr (void);
|
|
||||||
|
|
||||||
/* Call this from a netif driver (watch out for threading issues!) that has
|
|
||||||
returned a memory error on transmit and now has free buffers to send more.
|
|
||||||
This iterates all active pcbs that had an error and tries to call
|
|
||||||
tcp_output, so use this with care as it might slow down the system. */
|
|
||||||
void tcp_txnow (void);
|
|
||||||
|
|
||||||
/* Only used by IP to pass a TCP segment to TCP: */
|
|
||||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
|
||||||
/* Used within the TCP code only: */
|
|
||||||
struct tcp_pcb * tcp_alloc (u8_t prio);
|
|
||||||
void tcp_abandon (struct tcp_pcb *pcb, int reset);
|
|
||||||
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
|
|
||||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
|
||||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
|
||||||
void tcp_rexmit_fast (struct tcp_pcb *pcb);
|
|
||||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
|
||||||
err_t tcp_process_refused_data(struct tcp_pcb *pcb);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the Nagle algorithm: try to combine user data to send as few TCP
|
|
||||||
* segments as possible. Only send if
|
|
||||||
* - no previously transmitted data on the connection remains unacknowledged or
|
|
||||||
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
|
|
||||||
* - the only unsent segment is at least pcb->mss bytes long (or there is more
|
|
||||||
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
|
|
||||||
* - or if we are in fast-retransmit (TF_INFR)
|
|
||||||
*/
|
|
||||||
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
|
|
||||||
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
|
|
||||||
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
|
|
||||||
((tpcb)->unsent->len >= (tpcb)->mss))) || \
|
|
||||||
((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN(tpcb))) \
|
|
||||||
) ? 1 : 0)
|
|
||||||
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
|
|
||||||
|
|
||||||
|
|
||||||
#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0)
|
|
||||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0)
|
|
||||||
#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0)
|
|
||||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0)
|
|
||||||
/* is b<=a<=c? */
|
|
||||||
#if 0 /* see bug #10548 */
|
|
||||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
|
||||||
#endif
|
|
||||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
|
||||||
#define TCP_FIN 0x01U
|
|
||||||
#define TCP_SYN 0x02U
|
|
||||||
#define TCP_RST 0x04U
|
|
||||||
#define TCP_PSH 0x08U
|
|
||||||
#define TCP_ACK 0x10U
|
|
||||||
#define TCP_URG 0x20U
|
|
||||||
#define TCP_ECE 0x40U
|
|
||||||
#define TCP_CWR 0x80U
|
|
||||||
|
|
||||||
#define TCP_FLAGS 0x3fU
|
|
||||||
|
|
||||||
/* Length of the TCP header, excluding options. */
|
|
||||||
#define TCP_HLEN 20
|
|
||||||
|
|
||||||
#ifndef TCP_TMR_INTERVAL
|
|
||||||
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
|
|
||||||
#endif /* TCP_TMR_INTERVAL */
|
|
||||||
|
|
||||||
#ifndef TCP_FAST_INTERVAL
|
|
||||||
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
|
|
||||||
#endif /* TCP_FAST_INTERVAL */
|
|
||||||
|
|
||||||
#ifndef TCP_SLOW_INTERVAL
|
|
||||||
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
|
|
||||||
#endif /* TCP_SLOW_INTERVAL */
|
|
||||||
|
|
||||||
#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
|
|
||||||
#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
|
|
||||||
|
|
||||||
#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
|
|
||||||
|
|
||||||
#ifndef TCP_MSL
|
|
||||||
#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
|
|
||||||
#ifndef TCP_KEEPIDLE_DEFAULT
|
|
||||||
#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TCP_KEEPINTVL_DEFAULT
|
|
||||||
#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TCP_KEEPCNT_DEFAULT
|
|
||||||
#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
|
|
||||||
|
|
||||||
/* Fields are (of course) in network byte order.
|
|
||||||
* Some fields are converted to host byte order in tcp_input().
|
|
||||||
*/
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct tcp_hdr {
|
|
||||||
PACK_STRUCT_FIELD(u16_t src);
|
|
||||||
PACK_STRUCT_FIELD(u16_t dest);
|
|
||||||
PACK_STRUCT_FIELD(u32_t seqno);
|
|
||||||
PACK_STRUCT_FIELD(u32_t ackno);
|
|
||||||
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
|
|
||||||
PACK_STRUCT_FIELD(u16_t wnd);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u16_t urgp);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
|
|
||||||
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
|
|
||||||
|
|
||||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
|
||||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | htons(flags))
|
|
||||||
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
|
|
||||||
|
|
||||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
|
|
||||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~htons(flags))
|
|
||||||
|
|
||||||
#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U))
|
|
||||||
|
|
||||||
/** Flags used on input processing, not on pcb->flags
|
|
||||||
*/
|
|
||||||
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
|
|
||||||
#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */
|
|
||||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_EVENT_API
|
|
||||||
|
|
||||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_ACCEPT, NULL, 0, err)
|
|
||||||
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_SENT, NULL, space, ERR_OK)
|
|
||||||
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_RECV, (p), 0, (err))
|
|
||||||
#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_RECV, NULL, 0, ERR_OK)
|
|
||||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
|
||||||
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
|
||||||
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
|
|
||||||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
|
||||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
|
||||||
|
|
||||||
#else /* LWIP_EVENT_API */
|
|
||||||
|
|
||||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->accept != NULL) \
|
|
||||||
(ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
|
|
||||||
else (ret) = ERR_ARG; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->sent != NULL) \
|
|
||||||
(ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
|
|
||||||
else (ret) = ERR_OK; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->recv != NULL) { \
|
|
||||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\
|
|
||||||
} else { \
|
|
||||||
(ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_CLOSED(pcb,ret) \
|
|
||||||
do { \
|
|
||||||
if(((pcb)->recv != NULL)) { \
|
|
||||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\
|
|
||||||
} else { \
|
|
||||||
(ret) = ERR_OK; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->connected != NULL) \
|
|
||||||
(ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
|
|
||||||
else (ret) = ERR_OK; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_POLL(pcb,ret) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->poll != NULL) \
|
|
||||||
(ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
|
|
||||||
else (ret) = ERR_OK; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
|
||||||
do { \
|
|
||||||
if((errf) != NULL) \
|
|
||||||
(errf)((arg),(err)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif /* LWIP_EVENT_API */
|
|
||||||
|
|
||||||
/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */
|
|
||||||
#if TCP_OVERSIZE && defined(LWIP_DEBUG)
|
|
||||||
#define TCP_OVERSIZE_DBGCHECK 1
|
|
||||||
#else
|
|
||||||
#define TCP_OVERSIZE_DBGCHECK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */
|
|
||||||
#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP)
|
|
||||||
|
|
||||||
/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */
|
|
||||||
struct tcp_seg {
|
|
||||||
struct tcp_seg *next; /* used when putting segments on a queue */
|
|
||||||
struct pbuf *p; /* buffer containing data + TCP header */
|
|
||||||
u16_t len; /* the TCP length of this segment */
|
|
||||||
#if TCP_OVERSIZE_DBGCHECK
|
|
||||||
u16_t oversize_left; /* Extra bytes available at the end of the last
|
|
||||||
pbuf in unsent (used for asserting vs.
|
|
||||||
tcp_pcb.unsent_oversized only) */
|
|
||||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
|
||||||
#if TCP_CHECKSUM_ON_COPY
|
|
||||||
u16_t chksum;
|
|
||||||
u8_t chksum_swapped;
|
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
|
||||||
u8_t flags;
|
|
||||||
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
|
||||||
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
|
||||||
#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is
|
|
||||||
checksummed into 'chksum' */
|
|
||||||
#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */
|
|
||||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LWIP_TCP_OPT_EOL 0
|
|
||||||
#define LWIP_TCP_OPT_NOP 1
|
|
||||||
#define LWIP_TCP_OPT_MSS 2
|
|
||||||
#define LWIP_TCP_OPT_WS 3
|
|
||||||
#define LWIP_TCP_OPT_TS 8
|
|
||||||
|
|
||||||
#define LWIP_TCP_OPT_LEN_MSS 4
|
|
||||||
#if LWIP_TCP_TIMESTAMPS
|
|
||||||
#define LWIP_TCP_OPT_LEN_TS 10
|
|
||||||
#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */
|
|
||||||
#else
|
|
||||||
#define LWIP_TCP_OPT_LEN_TS_OUT 0
|
|
||||||
#endif
|
|
||||||
#if LWIP_WND_SCALE
|
|
||||||
#define LWIP_TCP_OPT_LEN_WS 3
|
|
||||||
#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */
|
|
||||||
#else
|
|
||||||
#define LWIP_TCP_OPT_LEN_WS_OUT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LWIP_TCP_OPT_LENGTH(flags) \
|
|
||||||
(flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \
|
|
||||||
(flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \
|
|
||||||
(flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0)
|
|
||||||
|
|
||||||
/** This returns a TCP header option for MSS in an u32_t */
|
|
||||||
#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF))
|
|
||||||
|
|
||||||
#if LWIP_WND_SCALE
|
|
||||||
#define TCPWNDSIZE_F U32_F
|
|
||||||
#define TCPWND_MAX 0xFFFFFFFFU
|
|
||||||
#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF)
|
|
||||||
#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF))
|
|
||||||
#else /* LWIP_WND_SCALE */
|
|
||||||
#define TCPWNDSIZE_F U16_F
|
|
||||||
#define TCPWND_MAX 0xFFFFU
|
|
||||||
#define TCPWND_CHECK16(x)
|
|
||||||
#define TCPWND_MIN16(x) x
|
|
||||||
#endif /* LWIP_WND_SCALE */
|
|
||||||
|
|
||||||
/* Global variables: */
|
|
||||||
extern struct tcp_pcb *tcp_input_pcb;
|
|
||||||
extern u32_t tcp_ticks;
|
|
||||||
extern u8_t tcp_active_pcbs_changed;
|
|
||||||
|
|
||||||
/* The TCP PCB lists. */
|
|
||||||
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
|
||||||
struct tcp_pcb_listen *listen_pcbs;
|
|
||||||
struct tcp_pcb *pcbs;
|
|
||||||
};
|
|
||||||
extern struct tcp_pcb *tcp_bound_pcbs;
|
|
||||||
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
|
||||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
|
||||||
state in which they accept or send
|
|
||||||
data. */
|
|
||||||
extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
|
||||||
|
|
||||||
#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
|
|
||||||
#define NUM_TCP_PCB_LISTS 4
|
|
||||||
extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
|
|
||||||
|
|
||||||
/* Axioms about the above lists:
|
|
||||||
1) Every TCP PCB that is not CLOSED is in one of the lists.
|
|
||||||
2) A PCB is only in one of the lists.
|
|
||||||
3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
|
|
||||||
4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
|
|
||||||
*/
|
|
||||||
/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
|
|
||||||
with a PCB list or removes a PCB from a list, respectively. */
|
|
||||||
#ifndef TCP_DEBUG_PCB_LISTS
|
|
||||||
#define TCP_DEBUG_PCB_LISTS 0
|
|
||||||
#endif
|
|
||||||
#if TCP_DEBUG_PCB_LISTS
|
|
||||||
#define TCP_REG(pcbs, npcb) do {\
|
|
||||||
struct tcp_pcb *tcp_tmp_pcb; \
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \
|
|
||||||
for (tcp_tmp_pcb = *(pcbs); \
|
|
||||||
tcp_tmp_pcb != NULL; \
|
|
||||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
|
||||||
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
|
|
||||||
} \
|
|
||||||
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
|
|
||||||
(npcb)->next = *(pcbs); \
|
|
||||||
LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
|
|
||||||
*(pcbs) = (npcb); \
|
|
||||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
|
||||||
tcp_timer_needed(); \
|
|
||||||
} while(0)
|
|
||||||
#define TCP_RMV(pcbs, npcb) do { \
|
|
||||||
struct tcp_pcb *tcp_tmp_pcb; \
|
|
||||||
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \
|
|
||||||
if(*(pcbs) == (npcb)) { \
|
|
||||||
*(pcbs) = (*pcbs)->next; \
|
|
||||||
} else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
|
||||||
if(tcp_tmp_pcb->next == (npcb)) { \
|
|
||||||
tcp_tmp_pcb->next = (npcb)->next; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
(npcb)->next = NULL; \
|
|
||||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#else /* LWIP_DEBUG */
|
|
||||||
|
|
||||||
#define TCP_REG(pcbs, npcb) \
|
|
||||||
do { \
|
|
||||||
(npcb)->next = *pcbs; \
|
|
||||||
*(pcbs) = (npcb); \
|
|
||||||
tcp_timer_needed(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_RMV(pcbs, npcb) \
|
|
||||||
do { \
|
|
||||||
if(*(pcbs) == (npcb)) { \
|
|
||||||
(*(pcbs)) = (*pcbs)->next; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
struct tcp_pcb *tcp_tmp_pcb; \
|
|
||||||
for (tcp_tmp_pcb = *pcbs; \
|
|
||||||
tcp_tmp_pcb != NULL; \
|
|
||||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
|
||||||
if(tcp_tmp_pcb->next == (npcb)) { \
|
|
||||||
tcp_tmp_pcb->next = (npcb)->next; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
(npcb)->next = NULL; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
|
|
||||||
#define TCP_REG_ACTIVE(npcb) \
|
|
||||||
do { \
|
|
||||||
TCP_REG(&tcp_active_pcbs, npcb); \
|
|
||||||
tcp_active_pcbs_changed = 1; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_RMV_ACTIVE(npcb) \
|
|
||||||
do { \
|
|
||||||
TCP_RMV(&tcp_active_pcbs, npcb); \
|
|
||||||
tcp_active_pcbs_changed = 1; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TCP_PCB_REMOVE_ACTIVE(pcb) \
|
|
||||||
do { \
|
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, pcb); \
|
|
||||||
tcp_active_pcbs_changed = 1; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal functions: */
|
|
||||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
|
||||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
|
||||||
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
|
|
||||||
|
|
||||||
void tcp_segs_free(struct tcp_seg *seg);
|
|
||||||
void tcp_seg_free(struct tcp_seg *seg);
|
|
||||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
|
||||||
|
|
||||||
#define tcp_ack(pcb) \
|
|
||||||
do { \
|
|
||||||
if((pcb)->flags & TF_ACK_DELAY) { \
|
|
||||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
|
||||||
(pcb)->flags |= TF_ACK_NOW; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
(pcb)->flags |= TF_ACK_DELAY; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define tcp_ack_now(pcb) \
|
|
||||||
do { \
|
|
||||||
(pcb)->flags |= TF_ACK_NOW; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
err_t tcp_send_fin(struct tcp_pcb *pcb);
|
|
||||||
err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
|
|
||||||
|
|
||||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
|
||||||
|
|
||||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
|
||||||
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
|
||||||
u16_t local_port, u16_t remote_port);
|
|
||||||
|
|
||||||
u32_t tcp_next_iss(void);
|
|
||||||
|
|
||||||
err_t tcp_keepalive(struct tcp_pcb *pcb);
|
|
||||||
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
|
|
||||||
void tcp_trigger_input_pcb_close(void);
|
|
||||||
|
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
|
||||||
u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest
|
|
||||||
#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING
|
|
||||||
, const ip_addr_t *src
|
|
||||||
#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */
|
|
||||||
);
|
|
||||||
#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING
|
|
||||||
#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src)
|
|
||||||
#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */
|
|
||||||
#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest)
|
|
||||||
#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */
|
|
||||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
|
||||||
|
|
||||||
#if LWIP_CALLBACK_API
|
|
||||||
err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
|
||||||
#endif /* LWIP_CALLBACK_API */
|
|
||||||
|
|
||||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
|
||||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
|
||||||
void tcp_debug_print_flags(u8_t flags);
|
|
||||||
void tcp_debug_print_state(enum tcp_state s);
|
|
||||||
void tcp_debug_print_pcbs(void);
|
|
||||||
s16_t tcp_pcbs_sane(void);
|
|
||||||
#else
|
|
||||||
# define tcp_debug_print(tcphdr)
|
|
||||||
# define tcp_debug_print_flags(flags)
|
|
||||||
# define tcp_debug_print_state(s)
|
|
||||||
# define tcp_debug_print_pcbs()
|
|
||||||
# define tcp_pcbs_sane() 1
|
|
||||||
#endif /* TCP_DEBUG */
|
|
||||||
|
|
||||||
/** External function (implemented in timers.c), called when TCP detects
|
|
||||||
* that a timer is needed (i.e. active- or time-wait-pcb found). */
|
|
||||||
void tcp_timer_needed(void);
|
|
||||||
|
|
||||||
#if LWIP_IPV4
|
|
||||||
void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr);
|
|
||||||
#endif /* LWIP_IPV4 */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_TCP_H */
|
|
|
@ -1,163 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_TCPIP_PRIV_H
|
|
||||||
#define LWIP_HDR_TCPIP_PRIV_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/tcpip.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/timers.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct pbuf;
|
|
||||||
struct netif;
|
|
||||||
|
|
||||||
/** Define this to something that triggers a watchdog. This is called from
|
|
||||||
* tcpip_thread after processing a message. */
|
|
||||||
#ifndef LWIP_TCPIP_THREAD_ALIVE
|
|
||||||
#define LWIP_TCPIP_THREAD_ALIVE()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
/** The global semaphore to lock the stack. */
|
|
||||||
extern sys_mutex_t lock_tcpip_core;
|
|
||||||
#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
|
|
||||||
#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
|
|
||||||
#else /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
#define LOCK_TCPIP_CORE()
|
|
||||||
#define UNLOCK_TCPIP_CORE()
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
#if LWIP_MPU_COMPATIBLE
|
|
||||||
#define API_VAR_REF(name) (*(name))
|
|
||||||
#define API_VAR_DECLARE(type, name) type * name
|
|
||||||
#define API_VAR_ALLOC(type, pool, name) do { \
|
|
||||||
name = (type *)memp_malloc(pool); \
|
|
||||||
if (name == NULL) { \
|
|
||||||
return ERR_MEM; \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
#define API_VAR_ALLOC_DONTFAIL(type, pool, name) do { \
|
|
||||||
name = (type *)memp_malloc(pool); \
|
|
||||||
LWIP_ASSERT("pool empty", name != NULL); \
|
|
||||||
} while(0)
|
|
||||||
#define API_VAR_FREE(pool, name) memp_free(pool, name)
|
|
||||||
#define API_EXPR_REF(expr) &(expr)
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
#define API_EXPR_REF_SEM(expr) (expr)
|
|
||||||
#else
|
|
||||||
#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr)
|
|
||||||
#endif
|
|
||||||
#define API_EXPR_DEREF(expr) expr
|
|
||||||
#else /* LWIP_MPU_COMPATIBLE */
|
|
||||||
#define API_VAR_REF(name) name
|
|
||||||
#define API_VAR_DECLARE(type, name) type name
|
|
||||||
#define API_VAR_ALLOC(type, pool, name)
|
|
||||||
#define API_VAR_ALLOC_DONTFAIL(type, pool, name)
|
|
||||||
#define API_VAR_FREE(pool, name)
|
|
||||||
#define API_EXPR_REF(expr) expr
|
|
||||||
#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr)
|
|
||||||
#define API_EXPR_DEREF(expr) *(expr)
|
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
|
||||||
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
err_t tcpip_send_api_msg(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem);
|
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
|
|
||||||
struct tcpip_api_call;
|
|
||||||
typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call* call);
|
|
||||||
struct tcpip_api_call
|
|
||||||
{
|
|
||||||
tcpip_api_call_fn function;
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
|
||||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
||||||
sys_sem_t *sem;
|
|
||||||
#else /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
sys_sem_t sem;
|
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
|
||||||
err_t err;
|
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
|
||||||
};
|
|
||||||
err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call *call);
|
|
||||||
|
|
||||||
enum tcpip_msg_type {
|
|
||||||
TCPIP_MSG_API,
|
|
||||||
TCPIP_MSG_API_CALL,
|
|
||||||
TCPIP_MSG_INPKT,
|
|
||||||
#if LWIP_TCPIP_TIMEOUT
|
|
||||||
TCPIP_MSG_TIMEOUT,
|
|
||||||
TCPIP_MSG_UNTIMEOUT,
|
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
|
||||||
TCPIP_MSG_CALLBACK,
|
|
||||||
TCPIP_MSG_CALLBACK_STATIC
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tcpip_msg {
|
|
||||||
enum tcpip_msg_type type;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
tcpip_callback_fn function;
|
|
||||||
void* msg;
|
|
||||||
} api;
|
|
||||||
struct tcpip_api_call *api_call;
|
|
||||||
struct {
|
|
||||||
struct pbuf *p;
|
|
||||||
struct netif *netif;
|
|
||||||
netif_input_fn input_fn;
|
|
||||||
} inp;
|
|
||||||
struct {
|
|
||||||
tcpip_callback_fn function;
|
|
||||||
void *ctx;
|
|
||||||
} cb;
|
|
||||||
#if LWIP_TCPIP_TIMEOUT
|
|
||||||
struct {
|
|
||||||
u32_t msecs;
|
|
||||||
sys_timeout_handler h;
|
|
||||||
void *arg;
|
|
||||||
} tmo;
|
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
|
||||||
} msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_TCPIP_PRIV_H */
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_HDR_RAW_H
|
|
||||||
#define LWIP_HDR_RAW_H
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/ip.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/ip6_addr.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct raw_pcb;
|
|
||||||
|
|
||||||
/** Function prototype for raw pcb receive callback functions.
|
|
||||||
* @param arg user supplied argument (raw_pcb.recv_arg)
|
|
||||||
* @param pcb the raw_pcb which received data
|
|
||||||
* @param p the packet buffer that was received
|
|
||||||
* @param addr the remote IP address from which the packet was received
|
|
||||||
* @return 1 if the packet was 'eaten' (aka. deleted),
|
|
||||||
* 0 if the packet lives on
|
|
||||||
* If returning 1, the callback is responsible for freeing the pbuf
|
|
||||||
* if it's not used any more.
|
|
||||||
*/
|
|
||||||
typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
|
||||||
const ip_addr_t *addr);
|
|
||||||
|
|
||||||
struct raw_pcb {
|
|
||||||
/* Common members of all PCB types */
|
|
||||||
IP_PCB;
|
|
||||||
|
|
||||||
struct raw_pcb *next;
|
|
||||||
|
|
||||||
u8_t protocol;
|
|
||||||
|
|
||||||
/** receive callback function */
|
|
||||||
raw_recv_fn recv;
|
|
||||||
/* user-supplied argument for the recv callback */
|
|
||||||
void *recv_arg;
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/* fields for handling checksum computations as per RFC3542. */
|
|
||||||
u16_t chksum_offset;
|
|
||||||
u8_t chksum_reqd;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The following functions is the application layer interface to the
|
|
||||||
RAW code. */
|
|
||||||
struct raw_pcb * raw_new (u8_t proto);
|
|
||||||
struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto);
|
|
||||||
void raw_remove (struct raw_pcb *pcb);
|
|
||||||
err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
|
||||||
err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
|
||||||
|
|
||||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr);
|
|
||||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
|
||||||
|
|
||||||
void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
|
|
||||||
|
|
||||||
/* The following functions are the lower layer interface to RAW. */
|
|
||||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
|
||||||
#define raw_init() /* Compatibility define, no init needed. */
|
|
||||||
|
|
||||||
/* for compatibility with older implementation */
|
|
||||||
#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_RAW */
|
|
||||||
|
|
||||||
#endif /* LWIP_HDR_RAW_H */
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue