mirror of https://github.com/ARMmbed/mbed-os.git
Merged lwip 2.0.1 stable to mbed-os
* commit '61a7b15741c964dfa1f1a14244de38ea4e2ce22a': Squashed 'features/FEATURE_LWIP/lwip-interface/lwip/' changes from d7a6c6d..10f93f4pull/3721/head
commit
b62df0033f
|
@ -1,4 +1,6 @@
|
|||
/doc/doxygen/output
|
||||
*.o
|
||||
*.a
|
||||
/doc/doxygen/output/html
|
||||
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
|
||||
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
|
||||
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler/bin/
|
||||
|
@ -11,3 +13,6 @@
|
|||
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
|
||||
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
|
||||
/src/apps/snmp/LwipMibCompiler/*.suo
|
||||
/test/fuzz/output
|
||||
/test/fuzz/lwip_fuzz
|
||||
/test/fuzz/.depend
|
||||
|
|
|
@ -3,6 +3,77 @@ HISTORY
|
|||
(git master)
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
++ New features:
|
||||
|
||||
2016-12-31: Simon Goldschmidt
|
||||
* tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error
|
||||
reason when listening fails (bug #49861)
|
||||
|
||||
2016-12-20: Erik Andersen
|
||||
* Add MQTT client
|
||||
|
||||
2016-12-14: Jan Breuer:
|
||||
* opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106)
|
||||
|
||||
2016-12-14: David van Moolenbroek
|
||||
* opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW()
|
||||
|
||||
2016-12-09: Dirk Ziegelmeier
|
||||
* ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF
|
||||
|
||||
2016-12-09: Simon Goldschmidt
|
||||
* dns.c: added one-shot multicast DNS queries
|
||||
|
||||
2016-11-24: Ambroz Bizjak, David van Moolenbroek
|
||||
* tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290)
|
||||
|
||||
2016-11-16: Dirk Ziegelmeier
|
||||
* sockets.c: added support for IPv6 mapped IPv4 addresses
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2016-12-16: Thomas Mueller
|
||||
* api_lib.c: fixed race condition in return value of netconn_gethostbyname()
|
||||
(and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo())
|
||||
|
||||
2016-12-15: David van Moolenbroek
|
||||
* opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial
|
||||
sequence numbers (see contrib/addons/tcp_isn for an example implementation)
|
||||
|
||||
2016-12-05: Dirk Ziegelmeier
|
||||
* fixed compiling with IPv4 disabled (IPv6 only case)
|
||||
|
||||
2016-11-28: Simon Goldschmidt
|
||||
* api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return
|
||||
ERR_OK without all bytes being written)
|
||||
|
||||
2016-11-28: Ambroz Bizjak
|
||||
* tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK
|
||||
assumed scaled)
|
||||
|
||||
2016-11-25: Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options)
|
||||
|
||||
2016-11-23: Dirk Ziegelmeier
|
||||
* udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB
|
||||
(and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY
|
||||
|
||||
2016-11-16: Dirk Ziegelmeier
|
||||
* *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API
|
||||
|
||||
2016-11-14: Joel Cunningham
|
||||
* tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit
|
||||
in window)
|
||||
|
||||
2016-11-16: Roberto Barbieri Carrera
|
||||
* autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address)
|
||||
|
||||
2016-11-11: Dirk Ziegelmeier
|
||||
* sockets.c: fixed bug #49578 (dropping multicast membership does not work
|
||||
with LWIP_SOCKET_OFFSET)
|
||||
|
||||
(STABLE-2.0.0)
|
||||
|
||||
++ New features:
|
||||
|
||||
|
@ -328,8 +399,9 @@ HISTORY
|
|||
|
||||
++ Bugfixes:
|
||||
|
||||
2016-11-25: Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options)
|
||||
2016-08-23: Simon Goldschmidt
|
||||
* etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need
|
||||
it any more after implementing unicast ARP renewal towards arp entry timeout
|
||||
|
||||
2016-07-20: Simon Goldschmidt
|
||||
* memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
src/ - The source code for the lwIP TCP/IP stack.
|
||||
doc/ - The documentation for lwIP.
|
||||
test/ - Some code to test whether the sources do what they should.
|
||||
|
||||
See also the FILES file in each subdirectory.
|
||||
|
|
|
@ -35,6 +35,9 @@ APPLICATIONS
|
|||
* HTTP server with SSI and CGI
|
||||
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol)
|
||||
* SNTP (Simple network time protocol)
|
||||
* NetBIOS name service responder
|
||||
* MDNS (Multicast DNS) responder
|
||||
* iPerf server implementation
|
||||
|
||||
|
||||
LICENSE
|
||||
|
@ -77,7 +80,7 @@ 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
|
||||
There is now a constantly growing wiki about lwIP at
|
||||
http://lwip.wikia.com/wiki/LwIP_Wiki
|
||||
|
||||
Also, there are mailing lists you can subscribe at
|
||||
|
|
|
@ -8,7 +8,14 @@ with newer versions.
|
|||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
* TODO
|
||||
(2.0.1)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
|
||||
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
|
||||
ip_current_netif() to the desired netif for every packet.
|
||||
See bug #49662 for an explanation.
|
||||
|
||||
(2.0.0)
|
||||
|
||||
|
@ -20,7 +27,7 @@ with newer versions.
|
|||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||
* Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
|
||||
* Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
|
||||
supports SNMP2vc (experimental v3 support)
|
||||
supports SNMPv2c (experimental v3 support)
|
||||
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
|
||||
|
||||
+++ Raw API:
|
||||
|
@ -34,7 +41,8 @@ with newer versions.
|
|||
++ Port changes
|
||||
|
||||
+++ new files:
|
||||
* MANY new and moved files!
|
||||
* MANY new and moved files!
|
||||
* Added src/Filelists.mk for use in Makefile projects
|
||||
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
|
||||
to let abc.h only contain the actual application programmer's API
|
||||
|
||||
|
@ -45,6 +53,13 @@ with newer versions.
|
|||
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
|
||||
instead of using one per netconn (these semaphores are used even with core locking
|
||||
enabled as some longer lasting functions like big writes still need to delay)
|
||||
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
|
||||
in def.h (to be overridden in cc.h) instead of config
|
||||
options for netbiosns, httpd, dns, etc. ...
|
||||
* New abstraction for hton* and ntoh* functions in def.h.
|
||||
To override them, use the following in cc.h:
|
||||
#define lwip_htons(x) <your_htons>
|
||||
#define lwip_htonl(x) <your_htonl>
|
||||
|
||||
+++ new options:
|
||||
* TODO
|
||||
|
@ -56,6 +71,8 @@ with newer versions.
|
|||
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
|
||||
is now available
|
||||
|
||||
* Signature of LWIP_HOOK_VLAN_SET macro was changed
|
||||
|
||||
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
|
||||
or to move buffers to dedicated memory using compiler attributes
|
||||
|
||||
|
@ -68,6 +85,7 @@ with newer versions.
|
|||
|
||||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||
* Major rewrite of PPP (incl. keep-up with apache pppd)
|
||||
see doc/ppp.txt for an upgrading how-to
|
||||
* Major rewrite of SNMP (incl. MIB parser)
|
||||
* Fixed timing issues that might have lead to losing a DHCP lease
|
||||
* Made rx processing path more robust against crafted errors
|
||||
|
@ -77,7 +95,7 @@ with newer versions.
|
|||
* support PBUF_REF for RX packets
|
||||
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
|
||||
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
|
||||
* Moved and reorderd stats (mainly memp/mib2)
|
||||
* Moved and reordered stats (mainly memp/mib2)
|
||||
|
||||
(1.4.0)
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
doxygen/ - Configuration files and scripts to create the lwIP doxygen source
|
||||
documentation (found at http://www.nongnu.org/lwip/)
|
||||
|
||||
savannah.txt - How to obtain the current development source code.
|
||||
contrib.txt - How to contribute to lwIP as a developer.
|
||||
rawapi.txt - The documentation for the core API of lwIP.
|
||||
Also provides an overview about the other APIs and multithreading.
|
||||
snmp_agent.txt - The documentation for the lwIP SNMP agent.
|
||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||
ppp.txt - Documentation of the PPP interface for lwIP.
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
void eth_mac_irq()
|
||||
{
|
||||
/* Service MAC IRQ here */
|
||||
|
||||
/* Allocate pbuf from pool (avoid using heap in interrupts) */
|
||||
struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL);
|
||||
|
||||
if(p != NULL) {
|
||||
/* Copy ethernet frame into pbuf */
|
||||
pbuf_take(p, eth_data, eth_data_count);
|
||||
|
||||
/* Put in a queue which is processed in main loop */
|
||||
if(!queue_try_put(&queue, p)) {
|
||||
/* queue is full -> packet loss */
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static err_t netif_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
|
||||
}
|
||||
|
||||
lock_interrupts();
|
||||
pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0);
|
||||
/* Start MAC transmit here */
|
||||
unlock_interrupts();
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void netif_status_callback(struct netif *netif)
|
||||
{
|
||||
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
}
|
||||
|
||||
static err_t netif_init(struct netif *netif)
|
||||
{
|
||||
netif->linkoutput = netif_output;
|
||||
netif->output = etharp_output;
|
||||
netif->output_ip6 = ethip6_output;
|
||||
netif->mtu = ETHERNET_MTU;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
|
||||
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
|
||||
SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr));
|
||||
netif->hwaddr_len = sizeof(netif->hwaddr);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct netif netif;
|
||||
|
||||
lwip_init();
|
||||
|
||||
netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input);
|
||||
netif.name[0] = 'e';
|
||||
netif.name[1] = '0';
|
||||
netif_create_ip6_linklocal_address(&netif, 1);
|
||||
netif.ip6_autoconfig_enabled = 1;
|
||||
netif_set_status_callback(&netif, netif_status_callback);
|
||||
netif_set_default(&netif);
|
||||
netif_set_up(&netif);
|
||||
|
||||
/* Start DHCP and HTTPD */
|
||||
dhcp_init();
|
||||
httpd_init();
|
||||
|
||||
while(1) {
|
||||
/* Check link state, e.g. via MDIO communication with PHY */
|
||||
if(link_state_changed()) {
|
||||
if(link_is_up()) {
|
||||
netif_set_link_up(&netif);
|
||||
} else {
|
||||
netif_set_link_down(&netif);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for received frames, feed them to lwIP */
|
||||
lock_interrupts();
|
||||
struct pbuf* p = queue_try_get(&queue);
|
||||
unlock_interrupts();
|
||||
|
||||
if(p != NULL) {
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
|
||||
}
|
||||
|
||||
if(netif.input(p, &netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cyclic lwIP timers check */
|
||||
sys_check_timeouts();
|
||||
|
||||
/* your application goes here */
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ features of Savannah help us not lose users' input.
|
|||
bugtracker at Savannah.
|
||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
||||
both core and arch specific stuff please separate them so that the core can
|
||||
be applied separately while leaving the other patch 'open'. The prefered way
|
||||
be applied separately while leaving the other patch 'open'. The preferred way
|
||||
is to NOT touch archs you can't test and let maintainers take care of them.
|
||||
This is a good way to see if they are used at all - the same goes for unix
|
||||
netifs except tapif.
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
doxygen lwip.Doxyfile
|
||||
|
|
|
@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
|
|||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = "lwIP 2.0.0"
|
||||
PROJECT_NAME = "lwIP"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "lwIP 2.0.0"
|
||||
PROJECT_NUMBER = "2.0.1"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = Lightweight IP stack
|
||||
PROJECT_BRIEF = "Lightweight IP stack"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
|
@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES
|
|||
# will be relative from the directory where doxygen is started.
|
||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_PATH = ../../
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
||||
# path mentioned in the documentation of a class, which tells the reader which
|
||||
|
@ -781,7 +781,7 @@ WARN_LOGFILE =
|
|||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ../../src main_page.h
|
||||
INPUT = main_page.h ../../src
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
@ -2071,6 +2071,7 @@ INCLUDE_FILE_PATTERNS = *.h
|
|||
PREDEFINED = __DOXYGEN__=1 \
|
||||
NO_SYS=0 \
|
||||
SYS_LIGHTWEIGHT_PROT=1 \
|
||||
LWIP_TCPIP_CORE_LOCKING=1 \
|
||||
LWIP_IPV4=1 \
|
||||
LWIP_IPV6=1 \
|
||||
LWIP_ICMP=1 \
|
||||
|
@ -2080,10 +2081,12 @@ PREDEFINED = __DOXYGEN__=1 \
|
|||
LWIP_UDP=1 \
|
||||
LWIP_IGMP=1 \
|
||||
LWIP_TCP=1 \
|
||||
TCP_LISTEN_BACKLOG=1 \
|
||||
LWIP_SNMP=1 \
|
||||
SNMP_USE_NETCONN=1 \
|
||||
SNMP_USE_RAW=1 \
|
||||
MIB2_STATS=1 \
|
||||
LWIP_MDNS_RESPONDER=1 \
|
||||
MEMP_OVERFLOW_CHECK=0 \
|
||||
MEMP_SANITY_CHECK=1 \
|
||||
LWIP_ARP=1 \
|
||||
|
@ -2091,8 +2094,10 @@ PREDEFINED = __DOXYGEN__=1 \
|
|||
LWIP_NETIF_HOSTNAME=1 \
|
||||
LWIP_NETIF_API=1 \
|
||||
LWIP_NETIF_CALLBACK=1 \
|
||||
LWIP_NETIF_STATUS_CALLBACK=1 \
|
||||
LWIP_NETIF_REMOVE_CALLBACK=1 \
|
||||
LWIP_NETIF_LINK_CALLBACK=1 \
|
||||
LWIP_NUM_NETIF_CLIENT_DATA=1 \
|
||||
ENABLE_LOOPBACK=1 \
|
||||
LWIP_AUTOIP=1 \
|
||||
ARP_QUEUEING=1 \
|
||||
|
@ -2110,10 +2115,8 @@ PREDEFINED = __DOXYGEN__=1 \
|
|||
SO_REUSE=1 \
|
||||
SO_REUSE_RXTOALL=1 \
|
||||
LWIP_HAVE_SLIPIF=1 \
|
||||
LWIP_6LOWPAN=1 \
|
||||
"LWIP_DNS && LWIP_SOCKET " \
|
||||
"(LWIP_DNS && LWIP_SOCKET)=1 "
|
||||
|
||||
LWIP_6LOWPAN=1
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
# macro definition that is found in the sources will be used. Use the PREDEFINED
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @defgroup lwip lwIP
|
||||
*
|
||||
* @defgroup infrastructure Infrastructure
|
||||
|
@ -7,8 +7,8 @@
|
|||
* Non thread-safe APIs, callback style for maximum performance and minimum
|
||||
* memory footprint.
|
||||
*
|
||||
* @defgroup threadsafe_api Thread-safe APIs
|
||||
* Thread-safe APIs, blocking functions. More overhead, but can be called
|
||||
* @defgroup sequential_api Sequential-style APIs
|
||||
* Sequential-style APIs, blocking functions. More overhead, but can be called
|
||||
* from any thread except TCPIP thread.
|
||||
*
|
||||
* @defgroup addons Addons
|
||||
|
@ -30,3 +30,98 @@
|
|||
* @page contrib How to contribute to lwIP
|
||||
* @verbinclude "contrib.txt"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page pitfalls Common pitfalls
|
||||
*
|
||||
* Multiple Execution Contexts in lwIP code
|
||||
* ========================================
|
||||
*
|
||||
* The most common source of lwIP problems is to have multiple execution contexts
|
||||
* inside the lwIP code.
|
||||
*
|
||||
* lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
|
||||
* running on target system) or @ref lwip_os (there is an OS running
|
||||
* on the target system).
|
||||
*
|
||||
* Mainloop Mode
|
||||
* -------------
|
||||
* In mainloop mode, only @ref callbackstyle_api can be used.
|
||||
* The user has two possibilities to ensure there is only one
|
||||
* exection context at a time in lwIP:
|
||||
*
|
||||
* 1) Deliver RX ethernet packets directly in interrupt context to lwIP
|
||||
* by calling netif->input directly in interrupt. This implies all lwIP
|
||||
* callback functions are called in IRQ context, which may cause further
|
||||
* problems in application code: IRQ is blocked for a long time, multiple
|
||||
* execution contexts in application code etc. When the application wants
|
||||
* to call lwIP, it only needs to disable interrupts during the call.
|
||||
* If timers are involved, even more locking code is needed to lock out
|
||||
* timer IRQ and ethernet IRQ from each other, assuming these may be nested.
|
||||
*
|
||||
* 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
|
||||
* lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
|
||||
* has to put received telegrams into a queue which is polled in the
|
||||
* mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* OS Mode
|
||||
* -------
|
||||
* In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
|
||||
* @ref sequential_api are designed to be called from threads other than
|
||||
* the TCPIP thread, so there is nothing to consider here.
|
||||
* But @ref callbackstyle_api functions must _ONLY_ be called from
|
||||
* TCPIP thread. It is a common error to call these from other threads
|
||||
* or from IRQ contexts. Ethernet RX needs to deliver incoming packets
|
||||
* in the correct way by sending a message to TCPIP thread, this is
|
||||
* implemented in tcpip_input().
|
||||
* Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* 1) tcpip_callback() can be used get called back from TCPIP thread,
|
||||
* it is safe to call any @ref callbackstyle_api from there.
|
||||
*
|
||||
* 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
|
||||
* functions can be called when lwIP core lock is aquired, see
|
||||
* @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
|
||||
* These macros cannot be used in an interrupt context!
|
||||
* Note the OS must correctly handle priority inversion for this.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page bugs Reporting bugs
|
||||
* Please report bugs in the lwIP bug tracker at savannah.\n
|
||||
* BEFORE submitting, please check if the bug has already been reported!\n
|
||||
* https://savannah.nongnu.org/bugs/?group=lwip
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
|
||||
* @ingroup lwip
|
||||
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
|
||||
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
|
||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
||||
* context and put them into a queue which is processed from mainloop.\n
|
||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
||||
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
|
||||
* @ref compiler_abstraction.\n
|
||||
* You can only use @ref callbackstyle_api in this mode.\n
|
||||
* Sample code:\n
|
||||
* @include NO_SYS_SampleCode.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_os OS mode (TCPIP thread)
|
||||
* @ingroup lwip
|
||||
* Use this mode if you run an OS on your system. It is recommended to
|
||||
* use an RTOS that correctly handles priority inversion and
|
||||
* to use @ref LWIP_TCPIP_CORE_LOCKING.\n
|
||||
* Porting: implement all functions in @ref sys_layer.\n
|
||||
* You can use @ref callbackstyle_api together with @ref tcpip_callback,
|
||||
* and all @ref sequential_api.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page raw_api lwIP API
|
||||
* @verbinclude "rawapi.txt"
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Redirection</title>
|
||||
<meta http-equiv="refresh" content="0; url=html/index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<a href="html/index.html">index.html</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,113 @@
|
|||
Multicast DNS for lwIP
|
||||
|
||||
Author: Erik Ekman
|
||||
|
||||
|
||||
Note! The MDNS responder does not have all features required by the standards.
|
||||
See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal
|
||||
cases - but watch out if many devices on the same network try to use the same
|
||||
host/service instance names.
|
||||
|
||||
|
||||
How to enable:
|
||||
==============
|
||||
|
||||
MDNS support does not depend on DNS.
|
||||
MDNS supports using IPv4 only, v6 only, or v4+v6.
|
||||
|
||||
To enable MDNS responder, set
|
||||
LWIP_MDNS_RESPONDER = 1
|
||||
in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build.
|
||||
|
||||
The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
|
||||
default is 1.
|
||||
|
||||
Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB.
|
||||
Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif).
|
||||
|
||||
MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
|
||||
MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
|
||||
generated.
|
||||
|
||||
The MDNS code puts its structs on the stack where suitable to reduce dynamic
|
||||
memory allocation. It may use up to 1kB of stack.
|
||||
|
||||
MDNS needs a strncasecmp() implementation. If you have one, define
|
||||
LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation
|
||||
for you.
|
||||
|
||||
|
||||
How to use:
|
||||
===========
|
||||
|
||||
Call mdns_resp_init() during system initialization.
|
||||
This opens UDP sockets on port 5353 for IPv4 and IPv6.
|
||||
|
||||
|
||||
To start responding on a netif, run
|
||||
mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
|
||||
|
||||
The hostname will be copied. If this returns successfully, the netif will join
|
||||
the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
|
||||
to port 5353 will be handled:
|
||||
- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
|
||||
- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
|
||||
returns <hostname>.local
|
||||
Answers will use the supplied TTL (in seconds)
|
||||
MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
|
||||
since the default case-insensitive comparison assumes this.
|
||||
|
||||
It is recommended to call this function after an IPv4 address has been set,
|
||||
since there is currently no check if the v4 address is valid.
|
||||
|
||||
Call mdns_resp_netif_settings_changed() every time the IP address
|
||||
on the netif has changed.
|
||||
|
||||
To stop responding on a netif, run
|
||||
mdns_resp_remove_netif(struct netif *netif)
|
||||
|
||||
|
||||
Adding services:
|
||||
================
|
||||
|
||||
The netif first needs to be registered. Then run
|
||||
mdns_resp_add_service(struct netif *netif, char *name, char *service,
|
||||
u16_t proto, u16_t port, u32_t dns_ttl,
|
||||
service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
|
||||
The name and service pointers will be copied. Name refers to the name of the
|
||||
service instance, and service is the type of service, like _http
|
||||
proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
|
||||
If this call returns successfully, the following queries will be answered:
|
||||
- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
|
||||
- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
|
||||
- <name>.<service>.<proto>.local type SRV returns hostname and port of service
|
||||
- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
|
||||
with the supplied userdata. The callback adds strings to the reply by calling
|
||||
mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
|
||||
int txt_len). Example callback method:
|
||||
|
||||
static void srv_txt(struct mdns_service *service, void *txt_userdata)
|
||||
{
|
||||
res = mdns_resp_add_service_txtitem(service, "path=/", 6);
|
||||
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
|
||||
}
|
||||
|
||||
Since a hostname struct is used for TXT storage each single item can be max
|
||||
63 bytes long, and the total max length (including length bytes for each
|
||||
item) is 255 bytes.
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
mdns_resp_add_service(netif, "myweb", "_http"
|
||||
DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
|
||||
|
||||
which will publish myweb._http._tcp.local for any hosts looking for web servers,
|
||||
and point them to <hostname>.local:80
|
||||
|
||||
Relevant information will be sent as additional records to reduce number of
|
||||
requests required from a client.
|
||||
|
||||
Removing services is currently not supported. Services are removed when the
|
||||
netif is removed.
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
MQTT client for lwIP
|
||||
|
||||
Author: Erik Andersson
|
||||
|
||||
Details of the MQTT protocol can be found at:
|
||||
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||
|
||||
-----------------------------------------------------------------
|
||||
1. Initial steps, reserve memory and make connection to server:
|
||||
|
||||
1.1: Provide storage
|
||||
|
||||
Static allocation:
|
||||
mqtt_client_t static_client;
|
||||
example_do_connect(&static_client);
|
||||
|
||||
Dynamic allocation:
|
||||
mqtt_client_t *client = mqtt_client_new();
|
||||
if(client != NULL) {
|
||||
example_do_connect(&client);
|
||||
}
|
||||
|
||||
1.2: Establish Connection with server
|
||||
|
||||
void example_do_connect(mqtt_client_t *client)
|
||||
{
|
||||
struct mqtt_connect_client_info_t ci;
|
||||
err_t err;
|
||||
|
||||
/* Setup an empty client info structure */
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
/* Minimal amount of information required is client identifier, so set it here */
|
||||
ci.client_id = "lwip_test";
|
||||
|
||||
/* Initiate client and connect to server, if this fails immediately an error code is returned
|
||||
otherwise mqtt_connection_cb will be called with connection result after attempting
|
||||
to establish a connection with the server.
|
||||
For now MQTT version 3.1.1 is always used */
|
||||
|
||||
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
|
||||
|
||||
/* For now just print the result code if something goes wrong
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_connect return %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
Connection to server can also be probed by calling mqtt_client_is_connected(client)
|
||||
|
||||
-----------------------------------------------------------------
|
||||
2. Implementing the connection status callback
|
||||
|
||||
|
||||
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
|
||||
{
|
||||
err_t err;
|
||||
if(status == MQTT_CONNECT_ACCEPTED) {
|
||||
printf("mqtt_connection_cb: Successfully connected\n");
|
||||
|
||||
/* Setup callback for incoming publish requests */
|
||||
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
|
||||
|
||||
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
|
||||
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
|
||||
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_subscribe return: %d\n", err);
|
||||
}
|
||||
} else {
|
||||
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
|
||||
|
||||
/* Its more nice to be connected, so try to reconnect */
|
||||
example_do_connect(client);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_sub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
/* Just print the result code here for simplicity,
|
||||
normal behaviour would be to take some action if subscribe fails like
|
||||
notifying user, retry subscribe or disconnect from server */
|
||||
printf("Subscribe result: %d\n", result);
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
3. Implementing callbacks for incoming publish and data
|
||||
|
||||
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
|
||||
Example here uses a global variable, better would be to use a member in arg
|
||||
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
|
||||
the topic string and use it in mqtt_incoming_data_cb
|
||||
*/
|
||||
static int inpub_id;
|
||||
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
|
||||
{
|
||||
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
|
||||
|
||||
/* Decode topic string into a user defined reference */
|
||||
if(strcmp(topic, "print_payload") == 0) {
|
||||
inpub_id = 0;
|
||||
} else if(topic[0] == 'A') {
|
||||
/* All topics starting with 'A' might be handled at the same way */
|
||||
inpub_id = 1;
|
||||
} else {
|
||||
/* For all other topics */
|
||||
inpub_id = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
|
||||
{
|
||||
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
|
||||
|
||||
if(flags & MQTT_DATA_FLAG_LAST) {
|
||||
/* Last fragment of payload received (or whole part if payload fits receive buffer
|
||||
See MQTT_VAR_HEADER_BUFFER_LEN) */
|
||||
|
||||
/* Call function or do action depending on reference, in this case inpub_id */
|
||||
if(inpub_id == 0) {
|
||||
/* Don't trust the publisher, check zero termination */
|
||||
if(data[len-1] == 0) {
|
||||
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
|
||||
}
|
||||
} else if(inpub_id == 1) {
|
||||
/* Call an 'A' function... */
|
||||
} else {
|
||||
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
|
||||
}
|
||||
} else {
|
||||
/* Handle fragmented payload, store in buffer, write to file or whatever */
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
4. Using outgoing publish
|
||||
|
||||
|
||||
void example_publish(mqtt_client_t *client, void *arg)
|
||||
{
|
||||
const char *pub_payload= "PubSubHubLubJub";
|
||||
err_t err;
|
||||
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
|
||||
u8_t retain = 0; /* No don't retain such crappy payload... */
|
||||
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
|
||||
if(err != ERR_OK) {
|
||||
printf("Publish err: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when publish is complete either with sucess or failure */
|
||||
static void mqtt_pub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
if(result != ERR_OK) {
|
||||
printf("Publish result: %d\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
5. Disconnecting
|
||||
|
||||
Simply call mqtt_disconnect(client)
|
|
@ -79,7 +79,7 @@ static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
|
|||
switch(err_code) {
|
||||
case PPPERR_NONE: {
|
||||
#if LWIP_DNS
|
||||
ip_addr_t ns;
|
||||
const ip_addr_t *ns;
|
||||
#endif /* LWIP_DNS */
|
||||
printf("status_cb: Connected\n");
|
||||
#if PPP_IPV4_SUPPORT
|
||||
|
@ -88,9 +88,9 @@ static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
|
|||
printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
|
||||
#if LWIP_DNS
|
||||
ns = dns_getserver(0);
|
||||
printf(" dns1 = %s\n", ipaddr_ntoa(&ns));
|
||||
printf(" dns1 = %s\n", ipaddr_ntoa(ns));
|
||||
ns = dns_getserver(1);
|
||||
printf(" dns2 = %s\n", ipaddr_ntoa(&ns));
|
||||
printf(" dns2 = %s\n", ipaddr_ntoa(ns));
|
||||
#endif /* LWIP_DNS */
|
||||
#endif /* PPP_IPV4_SUPPORT */
|
||||
#if PPP_IPV6_SUPPORT
|
||||
|
|
|
@ -171,15 +171,6 @@ incoming connections or be explicitly connected to another host.
|
|||
in the listen queue to the value specified by the backlog argument.
|
||||
To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
|
||||
|
||||
- void tcp_accepted(struct tcp_pcb *pcb)
|
||||
|
||||
Inform lwIP that an incoming connection has been accepted. This would
|
||||
usually be called from the accept callback. This allows lwIP to perform
|
||||
housekeeping tasks, such as allowing further incoming connections to be
|
||||
queued in the listen backlog.
|
||||
ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed
|
||||
into the accept callback!
|
||||
|
||||
- void tcp_accept(struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err))
|
||||
|
@ -465,9 +456,11 @@ introduction to this subject.
|
|||
Other significant improvements can be made by supplying
|
||||
assembly or inline replacements for htons() and htonl()
|
||||
if you're using a little-endian architecture.
|
||||
#define LWIP_PLATFORM_BYTESWAP 1
|
||||
#define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
#define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
#define lwip_htons(x) <your_htons>
|
||||
#define lwip_htonl(x) <your_htonl>
|
||||
If you #define them to htons() and htonl(), you should
|
||||
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
|
||||
defining hton*/ntoh* compatibility macros.
|
||||
|
||||
Check your network interface driver if it reads at
|
||||
a higher speed than the maximum wire-speed. If the
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
sys_arch interface for lwIP 0.6++
|
||||
sys_arch interface for lwIP
|
||||
|
||||
Author: Adam Dunkels
|
||||
Simon Goldschmidt
|
||||
|
||||
The operating system emulation layer provides a common interface
|
||||
between the lwIP code and the underlying operating system kernel. The
|
||||
|
@ -9,12 +10,11 @@ small changes to a few header files and a new sys_arch
|
|||
implementation. It is also possible to do a sys_arch implementation
|
||||
that does not rely on any underlying operating system.
|
||||
|
||||
The sys_arch provides semaphores and mailboxes to lwIP. For the full
|
||||
The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full
|
||||
lwIP functionality, multiple threads support can be implemented in the
|
||||
sys_arch, but this is not required for the basic lwIP
|
||||
functionality. Previous versions of lwIP required the sys_arch to
|
||||
implement timer scheduling as well but as of lwIP 0.5 this is
|
||||
implemented in a higher layer.
|
||||
functionality. Timer scheduling is implemented in lwIP, but can be implemented
|
||||
by the sys_arch port (LWIP_TIMERS_CUSTOM==1).
|
||||
|
||||
In addition to the source file providing the functionality of sys_arch,
|
||||
the OS emulation layer must provide several header files defining
|
||||
|
@ -22,19 +22,18 @@ macros used throughout lwip. The files required and the macros they
|
|||
must define are listed below the sys_arch description.
|
||||
|
||||
Semaphores can be either counting or binary - lwIP works with both
|
||||
kinds. Mailboxes are used for message passing and can be implemented
|
||||
either as a queue which allows multiple messages to be posted to a
|
||||
mailbox, or as a rendez-vous point where only one message can be
|
||||
posted at a time. lwIP works with both kinds, but the former type will
|
||||
be more efficient. A message in a mailbox is just a pointer, nothing
|
||||
more.
|
||||
kinds. Mailboxes should be implemented as a queue which allows multiple messages
|
||||
to be posted (implementing as a rendez-vous point where only one message can be
|
||||
posted at a time can have a highly negative impact on performance). A message
|
||||
in a mailbox is just a pointer, nothing more.
|
||||
|
||||
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
||||
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
||||
sys_sem_t or sys_mbox_t are represented internally.
|
||||
type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t".
|
||||
lwIP does not place any restrictions on how these types are represented
|
||||
internally.
|
||||
|
||||
Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that
|
||||
Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that
|
||||
allows both using pointers or actual OS structures to be used. This way, memory
|
||||
required for such types can be either allocated in place (globally or on the
|
||||
stack) or on the heap (allocated internally in the "*_new()" functions).
|
||||
|
@ -94,6 +93,40 @@ The following functions must be implemented by the sys_arch:
|
|||
sys_sem_free() is always called before calling this function!
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- void sys_mutex_new(sys_mutex_t *mutex)
|
||||
|
||||
Creates a new mutex. The mutex is allocated to the memory that 'mutex'
|
||||
points to (which can be both a pointer or the actual OS structure).
|
||||
If the mutex has been created, ERR_OK should be returned. Returning any
|
||||
other error will provide a hint what went wrong, but except for assertions,
|
||||
no real error handling is implemented.
|
||||
|
||||
- void sys_mutex_free(sys_mutex_t *mutex)
|
||||
|
||||
Deallocates a mutex.
|
||||
|
||||
- void sys_mutex_lock(sys_mutex_t *mutex)
|
||||
|
||||
Blocks the thread until the mutex can be grabbed.
|
||||
|
||||
- void sys_mutex_unlock(sys_mutex_t *mutex)
|
||||
|
||||
Releases the mutex previously locked through 'sys_mutex_lock()'.
|
||||
|
||||
- void sys_mutex_valid(sys_mutex_t *mutex)
|
||||
|
||||
Returns 1 if the mutes is valid, 0 if it is not valid.
|
||||
When using pointers, a simple way is to check the pointer for != NULL.
|
||||
When directly using OS structures, implementing this may be more complex.
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- void sys_mutex_set_invalid(sys_mutex_t *mutex)
|
||||
|
||||
Invalidate a mutex so that sys_mutex_valid() returns 0.
|
||||
ATTENTION: This does NOT mean that the mutex shall be deallocated:
|
||||
sys_mutex_free() is always called before calling this function!
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||
|
||||
Creates an empty mailbox for maximum "size" elements. Elements stored
|
||||
|
@ -176,6 +209,9 @@ to be implemented as well:
|
|||
the "stacksize" parameter. The id of the new thread is returned. Both the id
|
||||
and the priority are system dependent.
|
||||
|
||||
When lwIP is used from more than one context (e.g. from multiple threads OR from
|
||||
main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled!
|
||||
|
||||
- sys_prot_t sys_arch_protect(void)
|
||||
|
||||
This optional function does a "fast" critical region protection and returns
|
||||
|
@ -209,7 +245,7 @@ For some configurations, you also need:
|
|||
|
||||
Note:
|
||||
|
||||
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
||||
Be careful with using mem_malloc() in sys_arch. When malloc() refers to
|
||||
mem_malloc() you can run into a circular function call problem. In mem.c
|
||||
mem_init() tries to allcate a semaphore using mem_malloc, which of course
|
||||
can't be performed when sys_arch uses mem_malloc.
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
api/ - The code for the high-level wrapper API. Not needed if
|
||||
you use the lowel-level call-back/raw API.
|
||||
|
||||
apps/ - Higher layer applications that are specifically programmed
|
||||
with the lwIP low-level raw API.
|
||||
|
||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||
memory and buffer management, and the low-level raw API.
|
||||
|
||||
include/ - lwIP include files.
|
||||
|
||||
netif/ - Generic network interface device drivers are kept here,
|
||||
as well as the ARP module.
|
||||
netif/ - Generic network interface device drivers are kept here.
|
||||
|
||||
For more information on the various subdirectories, check the FILES
|
||||
file in each directory.
|
||||
|
|
|
@ -158,12 +158,24 @@ LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
|
|||
# SNTPFILES: SNTP client
|
||||
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
|
||||
|
||||
# MDNSFILES: MDNS responder
|
||||
MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
|
||||
|
||||
# NETBIOSNSFILES: NetBIOS name server
|
||||
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
|
||||
|
||||
# TFTPFILES: TFTP server files
|
||||
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
|
||||
|
||||
# MQTTFILES: MQTT client files
|
||||
MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c
|
||||
|
||||
# LWIPAPPFILES: All LWIP APPs
|
||||
LWIPAPPFILES=$(SNMPFILES) \
|
||||
$(HTTPDFILES) \
|
||||
$(LWIPERFFILES) \
|
||||
$(SNTPFILES) \
|
||||
$(NETBIOSNSFILES)
|
||||
$(MDNSFILES) \
|
||||
$(NETBIOSNSFILES) \
|
||||
$(TFTPFILES) \
|
||||
$(MQTTFILES)
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
/**
|
||||
* @file
|
||||
* Sequential API External module
|
||||
*
|
||||
* @defgroup netconn Netconn API
|
||||
* @ingroup sequential_api
|
||||
* Thread-safe, to be called from non-TCPIP threads only.
|
||||
* TX/RX handling based on @ref netbuf (containing @ref pbuf)
|
||||
* to avoid copying data around.
|
||||
*
|
||||
* @defgroup netconn_common Common functions
|
||||
* @ingroup netconn
|
||||
* For use with TCP and UDP
|
||||
*
|
||||
* @defgroup netconn_tcp TCP only
|
||||
* @ingroup netconn
|
||||
* TCP only functions
|
||||
*
|
||||
* @defgroup netconn_udp UDP only
|
||||
* @ingroup netconn
|
||||
* UDP only functions
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -34,26 +52,6 @@
|
|||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup netconn Netconn API
|
||||
* @ingroup threadsafe_api
|
||||
* Thread-safe, to be called from non-TCPIP threads only.
|
||||
* TX/RX handling based on @ref netbuf (containing @ref pbuf)
|
||||
* to avoid copying data around.
|
||||
*
|
||||
* @defgroup netconn_common Common functions
|
||||
* @ingroup netconn
|
||||
* For use with TCP and UDP
|
||||
*
|
||||
* @defgroup netconn_tcp TCP only
|
||||
* @ingroup netconn
|
||||
* TCP only functions
|
||||
*
|
||||
* @defgroup netconn_udp UDP only
|
||||
* @ingroup netconn
|
||||
* UDP only functions
|
||||
*/
|
||||
|
||||
/* This is the part of the API that is linked with
|
||||
the application */
|
||||
|
||||
|
@ -243,8 +241,8 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
|
|||
* 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 addr the local IP address to bind the netconn to
|
||||
* (use IP4_ADDR_ANY/IP6_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
|
||||
*/
|
||||
|
@ -256,10 +254,22 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|||
|
||||
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
#if LWIP_IPV4
|
||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||
if (addr == NULL) {
|
||||
addr = IP_ADDR_ANY;
|
||||
addr = IP4_ADDR_ANY;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
|
||||
* and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind
|
||||
*/
|
||||
if ((netconn_get_ipv6only(conn) == 0) &&
|
||||
ip_addr_cmp(addr, IP6_ADDR_ANY)) {
|
||||
addr = IP_ANY_TYPE;
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
API_MSG_VAR_ALLOC(msg);
|
||||
API_MSG_VAR_REF(msg).conn = conn;
|
||||
|
@ -288,10 +298,12 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|||
|
||||
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
#if LWIP_IPV4
|
||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||
if (addr == NULL) {
|
||||
addr = IP_ADDR_ANY;
|
||||
addr = IP4_ADDR_ANY;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
API_MSG_VAR_ALLOC(msg);
|
||||
API_MSG_VAR_REF(msg).conn = conn;
|
||||
|
@ -308,7 +320,7 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|||
* 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...
|
||||
* @return See @ref err_t
|
||||
*/
|
||||
err_t
|
||||
netconn_disconnect(struct netconn *conn)
|
||||
|
@ -378,7 +390,6 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|||
#if LWIP_TCP
|
||||
void *accept_ptr;
|
||||
struct netconn *newconn;
|
||||
err_t err;
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
API_MSG_VAR_DECLARE(msg);
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
@ -387,11 +398,10 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|||
*new_conn = NULL;
|
||||
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
err = conn->last_err;
|
||||
if (ERR_IS_FATAL(err)) {
|
||||
if (ERR_IS_FATAL(conn->last_err)) {
|
||||
/* don't recv on fatal errors: this might block the application task
|
||||
waiting on acceptmbox forever! */
|
||||
return err;
|
||||
return conn->last_err;
|
||||
}
|
||||
if (!sys_mbox_valid(&conn->acceptmbox)) {
|
||||
return ERR_CLSD;
|
||||
|
@ -467,7 +477,6 @@ 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);
|
||||
#if LWIP_MPU_COMPATIBLE
|
||||
|
@ -491,13 +500,12 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||
#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)) {
|
||||
if (ERR_IS_FATAL(conn->last_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;
|
||||
return conn->last_err;
|
||||
}
|
||||
#if LWIP_TCP
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
|
@ -546,6 +554,10 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||
/* 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);
|
||||
if (conn->pcb.ip == NULL) {
|
||||
/* race condition: RST during recv */
|
||||
return conn->last_err == ERR_OK ? ERR_RST : conn->last_err;
|
||||
}
|
||||
/* RX side is closed, so deallocate the recvmbox */
|
||||
netconn_close_shutdown(conn, NETCONN_SHUT_RD);
|
||||
/* Don' store ERR_CLSD as conn->err since we are only half-closed */
|
||||
|
@ -560,7 +572,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||
#if (LWIP_UDP || LWIP_RAW)
|
||||
{
|
||||
LWIP_ASSERT("buf != NULL", buf != NULL);
|
||||
len = netbuf_len((struct netbuf *)buf);
|
||||
len = netbuf_len((struct netbuf*)buf);
|
||||
}
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
|
||||
|
@ -695,6 +707,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
|||
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).conn = conn;
|
||||
API_MSG_VAR_REF(msg).msg.b = buf;
|
||||
|
@ -732,6 +745,11 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|||
return ERR_OK;
|
||||
}
|
||||
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
if (conn->send_timeout != 0) {
|
||||
dontblock = 1;
|
||||
}
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
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. */
|
||||
|
@ -759,11 +777,7 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|||
non-blocking version here. */
|
||||
err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
|
||||
if ((err == ERR_OK) && (bytes_written != NULL)) {
|
||||
if (dontblock
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
|| (conn->send_timeout != 0)
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
) {
|
||||
if (dontblock) {
|
||||
/* nonblocking write: maybe the data has been sent partly */
|
||||
*bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
|
||||
} else {
|
||||
|
@ -867,13 +881,15 @@ netconn_join_leave_group(struct netconn *conn,
|
|||
|
||||
API_MSG_VAR_ALLOC(msg);
|
||||
|
||||
#if LWIP_IPV4
|
||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||
if (multiaddr == NULL) {
|
||||
multiaddr = IP_ADDR_ANY;
|
||||
multiaddr = IP4_ADDR_ANY;
|
||||
}
|
||||
if (netif_addr == NULL) {
|
||||
netif_addr = IP_ADDR_ANY;
|
||||
netif_addr = IP4_ADDR_ANY;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
API_MSG_VAR_REF(msg).conn = conn;
|
||||
API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
|
||||
|
@ -912,6 +928,7 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
|||
sys_sem_t sem;
|
||||
#endif /* LWIP_MPU_COMPATIBLE */
|
||||
err_t err;
|
||||
err_t cberr;
|
||||
|
||||
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
|
||||
|
@ -944,13 +961,13 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
|||
}
|
||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||
|
||||
err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
|
||||
if (err != ERR_OK) {
|
||||
cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
|
||||
if (cberr != 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 err;
|
||||
return cberr;
|
||||
}
|
||||
sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
|
||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "lwip/priv/api_msg.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/raw.h"
|
||||
|
@ -540,18 +541,26 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||
* Called from lwip_netconn_do_newconn().
|
||||
*
|
||||
* @param msg the api_msg_msg describing the connection type
|
||||
* @return msg->conn->err, but the return value is currently ignored
|
||||
*/
|
||||
static void
|
||||
pcb_new(struct api_msg *msg)
|
||||
{
|
||||
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
|
||||
enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4;
|
||||
|
||||
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV4
|
||||
/* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */
|
||||
if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) {
|
||||
iptype = IPADDR_TYPE_ANY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate a PCB for this connection */
|
||||
switch(NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
|
||||
msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto);
|
||||
if (msg->conn->pcb.raw != NULL) {
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
}
|
||||
|
@ -559,7 +568,7 @@ pcb_new(struct api_msg *msg)
|
|||
#endif /* LWIP_RAW */
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
msg->conn->pcb.udp = udp_new_ip_type(iptype);
|
||||
if (msg->conn->pcb.udp != NULL) {
|
||||
#if LWIP_UDPLITE
|
||||
if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
|
||||
|
@ -575,7 +584,7 @@ pcb_new(struct api_msg *msg)
|
|||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
msg->conn->pcb.tcp = tcp_new_ip_type(iptype);
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
setup_tcp(msg->conn);
|
||||
}
|
||||
|
@ -589,15 +598,6 @@ pcb_new(struct api_msg *msg)
|
|||
if (msg->conn->pcb.ip == NULL) {
|
||||
msg->err = ERR_MEM;
|
||||
}
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
else {
|
||||
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||
/* Convert IPv4 PCB manually to an IPv6 PCB */
|
||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
|
||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -781,16 +781,18 @@ netconn_drain(struct netconn *conn)
|
|||
#if LWIP_TCP
|
||||
if (sys_mbox_valid(&conn->acceptmbox)) {
|
||||
while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
|
||||
struct netconn *newconn = (struct netconn *)mem;
|
||||
/* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
|
||||
/* pcb might be set to NULL already by err_tcp() */
|
||||
/* drain recvmbox */
|
||||
netconn_drain(newconn);
|
||||
if (newconn->pcb.tcp != NULL) {
|
||||
tcp_abort(newconn->pcb.tcp);
|
||||
newconn->pcb.tcp = NULL;
|
||||
if (mem != &netconn_aborted) {
|
||||
struct netconn *newconn = (struct netconn *)mem;
|
||||
/* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
|
||||
/* pcb might be set to NULL already by err_tcp() */
|
||||
/* drain recvmbox */
|
||||
netconn_drain(newconn);
|
||||
if (newconn->pcb.tcp != NULL) {
|
||||
tcp_abort(newconn->pcb.tcp);
|
||||
newconn->pcb.tcp = NULL;
|
||||
}
|
||||
netconn_free(newconn);
|
||||
}
|
||||
netconn_free(newconn);
|
||||
}
|
||||
sys_mbox_free(&conn->acceptmbox);
|
||||
sys_mbox_set_invalid(&conn->acceptmbox);
|
||||
|
@ -805,7 +807,6 @@ netconn_drain(struct netconn *conn)
|
|||
* places.
|
||||
*
|
||||
* @param conn the TCP netconn to close
|
||||
* [@param delay 1 if called from sent/poll (wake up calling thread on end)]
|
||||
*/
|
||||
static err_t
|
||||
lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM)
|
||||
|
@ -1113,37 +1114,20 @@ lwip_netconn_do_bind(void *m)
|
|||
} else {
|
||||
msg->err = ERR_VAL;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr);
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
|
||||
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
|
||||
*/
|
||||
if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) &&
|
||||
(netconn_get_ipv6only(msg->conn) == 0)) {
|
||||
/* change PCB type to IPADDR_TYPE_ANY */
|
||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
|
||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
|
||||
|
||||
/* bind to IPADDR_TYPE_ANY */
|
||||
ipaddr = IP_ANY_TYPE;
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->err = raw_bind(msg->conn->pcb.raw, ipaddr);
|
||||
msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
|
||||
break;
|
||||
#endif /* LWIP_RAW */
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDP:
|
||||
msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port);
|
||||
msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port);
|
||||
msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
|
@ -1323,6 +1307,13 @@ lwip_netconn_do_listen(void *m)
|
|||
/* connection is not closed, cannot listen */
|
||||
msg->err = ERR_VAL;
|
||||
} else {
|
||||
err_t err;
|
||||
u8_t backlog;
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
backlog = msg->msg.lb.backlog;
|
||||
#else /* TCP_LISTEN_BACKLOG */
|
||||
backlog = TCP_DEFAULT_LISTEN_BACKLOG;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
|
||||
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
|
||||
|
@ -1335,15 +1326,11 @@ lwip_netconn_do_listen(void *m)
|
|||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
|
||||
#else /* TCP_LISTEN_BACKLOG */
|
||||
lpcb = tcp_listen(msg->conn->pcb.tcp);
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err);
|
||||
|
||||
if (lpcb == NULL) {
|
||||
/* in this case, the old pcb is still allocated */
|
||||
msg->err = ERR_MEM;
|
||||
msg->err = err;
|
||||
} else {
|
||||
/* delete the recvmbox and allocate the acceptmbox */
|
||||
if (sys_mbox_valid(&msg->conn->recvmbox)) {
|
||||
|
@ -1400,7 +1387,7 @@ lwip_netconn_do_send(void *m)
|
|||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
||||
if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
|
||||
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
||||
} else {
|
||||
msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
|
||||
|
@ -1490,7 +1477,6 @@ lwip_netconn_do_accepted(void *m)
|
|||
* blocking application thread (waiting in netconn_write) is released.
|
||||
*
|
||||
* @param conn netconn (that is currently in state NETCONN_WRITE) to process
|
||||
* [@param delay 1 if called from sent/poll (wake up calling thread on end)]
|
||||
* @return ERR_OK
|
||||
* ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
|
||||
*/
|
||||
|
@ -1512,9 +1498,8 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM)
|
|||
LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
|
||||
conn->write_offset < conn->current_msg->msg.w.len);
|
||||
|
||||
dontblock = netconn_is_nonblocking(conn) ||
|
||||
(conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK);
|
||||
apiflags = conn->current_msg->msg.w.apiflags;
|
||||
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
||||
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
if ((conn->send_timeout != 0) &&
|
||||
|
@ -1590,10 +1575,11 @@ err_mem:
|
|||
write_finished = 1;
|
||||
conn->current_msg->msg.w.len = 0;
|
||||
}
|
||||
} else if ((err == ERR_MEM) && !dontblock) {
|
||||
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
|
||||
we do NOT return to the application thread, since ERR_MEM is
|
||||
only a temporary error! */
|
||||
} else if (err == ERR_MEM) {
|
||||
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called.
|
||||
For blocking sockets, we do NOT return to the application
|
||||
thread, since ERR_MEM is only a temporary error! Non-blocking
|
||||
will remain non-writable until sent_tcp/poll_tcp is called */
|
||||
|
||||
/* tcp_write returned ERR_MEM, try tcp_output anyway */
|
||||
err_t out_err = tcp_output(conn->pcb.tcp);
|
||||
|
@ -1604,7 +1590,11 @@ err_mem:
|
|||
err = out_err;
|
||||
write_finished = 1;
|
||||
conn->current_msg->msg.w.len = 0;
|
||||
} else {
|
||||
} else if (dontblock) {
|
||||
/* non-blocking write is done on ERR_MEM */
|
||||
err = ERR_WOULDBLOCK;
|
||||
write_finished = 1;
|
||||
conn->current_msg->msg.w.len = 0;
|
||||
}
|
||||
} else {
|
||||
/* On errors != ERR_MEM, we don't try writing any more but return
|
||||
|
@ -1713,6 +1703,7 @@ lwip_netconn_do_getaddr(void *m)
|
|||
ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
|
||||
msg->conn->pcb.ip->remote_ip);
|
||||
}
|
||||
|
||||
msg->err = ERR_OK;
|
||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
|
|
|
@ -37,6 +37,43 @@
|
|||
*/
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/errno.h"
|
||||
|
||||
#if !NO_SYS
|
||||
/** Table to quickly map an lwIP error (err_t) to a socket error
|
||||
* by using -err as an index */
|
||||
static const int err_to_errno_table[] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||
EALREADY, /* ERR_ALREADY -9 Already connecting. */
|
||||
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
|
||||
ENOTCONN, /* ERR_CONN -11 Not connected. */
|
||||
-1, /* ERR_IF -12 Low-level netif error */
|
||||
ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -14 Connection reset. */
|
||||
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
|
||||
EIO /* ERR_ARG -16 Illegal argument. */
|
||||
};
|
||||
|
||||
int
|
||||
err_to_errno(err_t err)
|
||||
{
|
||||
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
|
||||
return EIO;
|
||||
}
|
||||
return err_to_errno_table[-err];
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
|
@ -69,6 +106,9 @@ static const char *err_strerr[] = {
|
|||
const char *
|
||||
lwip_strerr(err_t err)
|
||||
{
|
||||
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) {
|
||||
return "Unknown error.";
|
||||
}
|
||||
return err_strerr[-err];
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
* @file
|
||||
* Network buffer management
|
||||
*
|
||||
* @defgroup netbuf Network buffers
|
||||
* @ingroup netconn
|
||||
* Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
|
||||
* to avoid copying data around.\n
|
||||
* Buffers must not be shared accross multiple threads, all functions except
|
||||
* netbuf_new() and netbuf_delete() are not thread-safe.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -36,15 +42,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup netbuf Network buffers
|
||||
* @ingroup netconn
|
||||
* Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
|
||||
* to avoid copying data around.\n
|
||||
* Buffers must not be shared accross multiple threads, all functions except
|
||||
* netbuf_new() and netbuf_delete() are not thread-safe.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
||||
|
@ -69,23 +66,9 @@ netbuf *netbuf_new(void)
|
|||
|
||||
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;
|
||||
memset(buf, 0, sizeof(struct netbuf));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,7 +171,7 @@ netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
|||
void
|
||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
{
|
||||
LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
|
||||
LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
|
||||
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
||||
pbuf_cat(head->p, tail->p);
|
||||
head->ptr = head->p;
|
||||
|
@ -234,7 +217,7 @@ netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
|||
s8_t
|
||||
netbuf_next(struct netbuf *buf)
|
||||
{
|
||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;);
|
||||
LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
|
||||
if (buf->ptr->next == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -256,7 +239,7 @@ netbuf_next(struct netbuf *buf)
|
|||
void
|
||||
netbuf_first(struct netbuf *buf)
|
||||
{
|
||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
||||
LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* @file
|
||||
* API functions for name resolving
|
||||
*
|
||||
* @defgroup netdbapi NETDB API
|
||||
* @ingroup socket
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -33,12 +35,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup netdbapi NETDB API
|
||||
* @ingroup socket
|
||||
*/
|
||||
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#if LWIP_DNS && LWIP_SOCKET
|
||||
|
@ -50,8 +46,8 @@
|
|||
#include "lwip/api.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memset */
|
||||
#include <stdlib.h> /* atoi */
|
||||
|
||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||
struct gethostbyname_r_helper {
|
||||
|
@ -379,17 +375,17 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
|||
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);
|
||||
sa6->sin6_port = lwip_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));
|
||||
inet_addr_from_ip4addr(&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);
|
||||
sa4->sin_port = lwip_htons((u16_t)port_nr);
|
||||
ai->ai_family = AF_INET;
|
||||
#endif /* LWIP_IPV4 */
|
||||
}
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
* @file
|
||||
* Network Interface Sequential API module
|
||||
*
|
||||
* @defgroup netifapi NETIF API
|
||||
* @ingroup sequential_api
|
||||
* Thread-safe functions to be called from non-TCPIP threads
|
||||
*
|
||||
* @defgroup netifapi_netif NETIF related
|
||||
* @ingroup netifapi
|
||||
* To be called from non-TCPIP threads
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -31,16 +38,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup netifapi NETIF API
|
||||
* @ingroup threadsafe_api
|
||||
* Thread-safe functions to be called from non-TCPIP threads
|
||||
*
|
||||
* @defgroup netifapi_netif NETIF related
|
||||
* @ingroup netifapi
|
||||
* To be called from non-TCPIP threads
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
|
||||
|
@ -137,13 +134,13 @@ netifapi_netif_add(struct netif *netif,
|
|||
|
||||
#if LWIP_IPV4
|
||||
if (ipaddr == NULL) {
|
||||
ipaddr = IP4_ADDR_ANY;
|
||||
ipaddr = IP4_ADDR_ANY4;
|
||||
}
|
||||
if (netmask == NULL) {
|
||||
netmask = IP4_ADDR_ANY;
|
||||
netmask = IP4_ADDR_ANY4;
|
||||
}
|
||||
if (gw == NULL) {
|
||||
gw = IP4_ADDR_ANY;
|
||||
gw = IP4_ADDR_ANY4;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
|
@ -180,13 +177,13 @@ netifapi_netif_set_addr(struct netif *netif,
|
|||
NETIFAPI_VAR_ALLOC(msg);
|
||||
|
||||
if (ipaddr == NULL) {
|
||||
ipaddr = IP4_ADDR_ANY;
|
||||
ipaddr = IP4_ADDR_ANY4;
|
||||
}
|
||||
if (netmask == NULL) {
|
||||
netmask = IP4_ADDR_ANY;
|
||||
netmask = IP4_ADDR_ANY4;
|
||||
}
|
||||
if (gw == NULL) {
|
||||
gw = IP4_ADDR_ANY;
|
||||
gw = IP4_ADDR_ANY4;
|
||||
}
|
||||
|
||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
* @file
|
||||
* Sockets BSD-Like API module
|
||||
*
|
||||
* @defgroup socket Socket API
|
||||
* @ingroup sequential_api
|
||||
* BSD-style socket API.\n
|
||||
* Thread-safe, to be called from non-TCPIP threads only.\n
|
||||
* Can be activated by defining @ref LWIP_SOCKET to 1.\n
|
||||
* Header is in posix/sys/socket.h\b
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -38,15 +44,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup socket Socket API
|
||||
* @ingroup threadsafe_api
|
||||
* BSD-style socket API.\n
|
||||
* Thread-safe, to be called from non-TCPIP threads only.\n
|
||||
* Can be activated by defining LWIP_SOCKET to 1.\n
|
||||
* Header is in posix/sys/socket.h\b
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||
|
@ -84,25 +81,25 @@
|
|||
#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
|
||||
(sin)->sin_len = sizeof(struct sockaddr_in); \
|
||||
(sin)->sin_family = AF_INET; \
|
||||
(sin)->sin_port = htons((port)); \
|
||||
inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \
|
||||
(sin)->sin_port = lwip_htons((port)); \
|
||||
inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
|
||||
memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
|
||||
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
|
||||
inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
|
||||
(port) = ntohs((sin)->sin_port); }while(0)
|
||||
inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
|
||||
(port) = lwip_ntohs((sin)->sin_port); }while(0)
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
|
||||
(sin6)->sin6_len = sizeof(struct sockaddr_in6); \
|
||||
(sin6)->sin6_family = AF_INET6; \
|
||||
(sin6)->sin6_port = htons((port)); \
|
||||
(sin6)->sin6_port = lwip_htons((port)); \
|
||||
(sin6)->sin6_flowinfo = 0; \
|
||||
inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
|
||||
(sin6)->sin6_scope_id = 0; }while(0)
|
||||
#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
|
||||
(port) = ntohs((sin6)->sin6_port); }while(0)
|
||||
(port) = lwip_ntohs((sin6)->sin6_port); }while(0)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
|
@ -269,8 +266,8 @@ union sockaddr_aligned {
|
|||
/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
|
||||
a socket is closed */
|
||||
struct lwip_socket_multicast_pair {
|
||||
/** the socket (+1 to not require initialization) */
|
||||
int sa;
|
||||
/** the socket */
|
||||
struct lwip_sock* sock;
|
||||
/** the interface address */
|
||||
ip4_addr_t if_addr;
|
||||
/** the group address */
|
||||
|
@ -292,34 +289,6 @@ static struct lwip_select_cb *select_cb_list;
|
|||
and checked in event_callback to see if it has changed. */
|
||||
static volatile int select_cb_ctr;
|
||||
|
||||
/** Table to quickly map an lwIP error (err_t) to a socket error
|
||||
* by using -err as an index */
|
||||
static const int err_to_errno_table[] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||
EALREADY, /* ERR_ALREADY -9 Already connecting. */
|
||||
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
|
||||
ENOTCONN, /* ERR_CONN -11 Not connected. */
|
||||
-1, /* ERR_IF -12 Low-level netif error */
|
||||
ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -14 Connection reset. */
|
||||
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
|
||||
EIO /* ERR_ARG -16 Illegal argument. */
|
||||
};
|
||||
|
||||
#define ERR_TO_ERRNO_TABLE_SIZE LWIP_ARRAYSIZE(err_to_errno_table)
|
||||
|
||||
#define err_to_errno(err) \
|
||||
((unsigned)(-(signed)(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
|
||||
err_to_errno_table[-(signed)(err)] : EIO)
|
||||
|
||||
#if LWIP_SOCKET_SET_ERRNO
|
||||
#ifndef set_errno
|
||||
#define set_errno(err) do { if (err) { errno = (err); } } while(0)
|
||||
|
@ -513,7 +482,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
|
||||
if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
set_errno(EWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -615,6 +584,14 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
|||
ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&local_addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
|
||||
IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
err = netconn_bind(sock->conn, &local_addr, local_port);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
|
@ -699,6 +676,14 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
|||
ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&remote_addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
|
||||
IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
err = netconn_connect(sock->conn, &remote_addr, remote_port);
|
||||
}
|
||||
|
||||
|
@ -786,7 +771,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||
return off;
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
set_errno(EWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -878,6 +863,15 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||
port = netbuf_fromport((struct netbuf *)buf);
|
||||
fromaddr = netbuf_fromaddr((struct netbuf *)buf);
|
||||
}
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */
|
||||
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
|
||||
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
|
||||
IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
||||
|
@ -972,8 +966,6 @@ int
|
|||
lwip_sendmsg(int s, const struct msghdr *msg, int flags)
|
||||
{
|
||||
struct lwip_sock *sock;
|
||||
struct netbuf *chain_buf;
|
||||
u16_t remote_port;
|
||||
int i;
|
||||
#if LWIP_TCP
|
||||
u8_t write_flags;
|
||||
|
@ -1030,82 +1022,93 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
|
|||
}
|
||||
/* else, UDP and RAW NETCONNs */
|
||||
#if LWIP_UDP || LWIP_RAW
|
||||
{
|
||||
struct netbuf *chain_buf;
|
||||
|
||||
LWIP_UNUSED_ARG(flags);
|
||||
LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
|
||||
IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
LWIP_UNUSED_ARG(flags);
|
||||
LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
|
||||
IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
|
||||
/* initialize chain buffer with destination */
|
||||
chain_buf = netbuf_new();
|
||||
if (!chain_buf) {
|
||||
sock_set_errno(sock, err_to_errno(ERR_MEM));
|
||||
return -1;
|
||||
}
|
||||
if (msg->msg_name) {
|
||||
SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
|
||||
netbuf_fromport(chain_buf) = remote_port;
|
||||
}
|
||||
/* initialize chain buffer with destination */
|
||||
chain_buf = netbuf_new();
|
||||
if (!chain_buf) {
|
||||
sock_set_errno(sock, err_to_errno(ERR_MEM));
|
||||
return -1;
|
||||
}
|
||||
if (msg->msg_name) {
|
||||
u16_t remote_port;
|
||||
SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
|
||||
netbuf_fromport(chain_buf) = remote_port;
|
||||
}
|
||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
size += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
/* Allocate a new netbuf and copy the data into it. */
|
||||
if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
|
||||
err = ERR_MEM;
|
||||
}
|
||||
else {
|
||||
/* flatten the IO vectors */
|
||||
size_t offset = 0;
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
|
||||
offset += msg->msg_iov[i].iov_len;
|
||||
size += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
{
|
||||
/* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */
|
||||
u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
|
||||
netbuf_set_chksum(chain_buf, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
err = ERR_OK;
|
||||
}
|
||||
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
/* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain
|
||||
manually to avoid having to allocate, chain, and delete a netbuf for each iov */
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
if (p == NULL) {
|
||||
err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */
|
||||
break;
|
||||
}
|
||||
p->payload = msg->msg_iov[i].iov_base;
|
||||
LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
|
||||
p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
|
||||
/* netbuf empty, add new pbuf */
|
||||
if (chain_buf->p == NULL) {
|
||||
chain_buf->p = chain_buf->ptr = p;
|
||||
/* add pbuf to existing pbuf chain */
|
||||
/* Allocate a new netbuf and copy the data into it. */
|
||||
if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
|
||||
err = ERR_MEM;
|
||||
} else {
|
||||
pbuf_cat(chain_buf->p, p);
|
||||
/* flatten the IO vectors */
|
||||
size_t offset = 0;
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
|
||||
offset += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
{
|
||||
/* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */
|
||||
u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
|
||||
netbuf_set_chksum(chain_buf, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
err = ERR_OK;
|
||||
}
|
||||
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
/* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain
|
||||
manually to avoid having to allocate, chain, and delete a netbuf for each iov */
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
if (p == NULL) {
|
||||
err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */
|
||||
break;
|
||||
}
|
||||
p->payload = msg->msg_iov[i].iov_base;
|
||||
LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
|
||||
p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
|
||||
/* netbuf empty, add new pbuf */
|
||||
if (chain_buf->p == NULL) {
|
||||
chain_buf->p = chain_buf->ptr = p;
|
||||
/* add pbuf to existing pbuf chain */
|
||||
} else {
|
||||
pbuf_cat(chain_buf->p, p);
|
||||
}
|
||||
}
|
||||
/* save size of total chain */
|
||||
if (err == ERR_OK) {
|
||||
size = netbuf_len(chain_buf);
|
||||
}
|
||||
}
|
||||
/* save size of total chain */
|
||||
if (err == ERR_OK) {
|
||||
size = netbuf_len(chain_buf);
|
||||
}
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
if (err == ERR_OK) {
|
||||
/* send the data */
|
||||
err = netconn_send(sock->conn, chain_buf);
|
||||
if (err == ERR_OK) {
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&chain_buf->addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
|
||||
IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
/* send the data */
|
||||
err = netconn_send(sock->conn, chain_buf);
|
||||
}
|
||||
|
||||
/* deallocated the buffer */
|
||||
netbuf_delete(chain_buf);
|
||||
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err == ERR_OK ? size : -1);
|
||||
}
|
||||
|
||||
/* deallocated the buffer */
|
||||
netbuf_delete(chain_buf);
|
||||
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err == ERR_OK ? size : -1);
|
||||
#else /* LWIP_UDP || LWIP_RAW */
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG));
|
||||
return -1;
|
||||
|
@ -1137,12 +1140,6 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
|
||||
/* sockaddr does not match socket type (IPv4/IPv6) */
|
||||
sock_set_errno(sock, err_to_errno(ERR_VAL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* @todo: split into multiple sendto's? */
|
||||
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
|
||||
short_size = (u16_t)size;
|
||||
|
@ -1192,6 +1189,14 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||
err = netbuf_ref(&buf, data, short_size);
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
if (err == ERR_OK) {
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&buf.addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
|
||||
IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
/* send the data */
|
||||
err = netconn_send(sock->conn, &buf);
|
||||
}
|
||||
|
@ -1209,9 +1214,7 @@ lwip_socket(int domain, int type, int protocol)
|
|||
struct netconn *conn;
|
||||
int i;
|
||||
|
||||
#if !LWIP_IPV6
|
||||
LWIP_UNUSED_ARG(domain); /* @todo: check this */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* create a netconn */
|
||||
switch (type) {
|
||||
|
@ -1274,7 +1277,7 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
|
|||
msg.msg_namelen = 0;
|
||||
/* Hack: we have to cast via number to cast from 'const' pointer to non-const.
|
||||
Blame the opengroup standard for this inconsistency. */
|
||||
msg.msg_iov = (struct iovec *)(size_t)iov;
|
||||
msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov);
|
||||
msg.msg_iovlen = iovcnt;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
@ -1288,12 +1291,12 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
|
|||
* the sockets enabled that had events.
|
||||
*
|
||||
* @param maxfdp1 the highest socket index in the sets
|
||||
* @param readset_in: set of sockets to check for read events
|
||||
* @param writeset_in: set of sockets to check for write events
|
||||
* @param exceptset_in: set of sockets to check for error events
|
||||
* @param readset_out: set of sockets that had read events
|
||||
* @param writeset_out: set of sockets that had write events
|
||||
* @param exceptset_out: set os sockets that had error events
|
||||
* @param readset_in set of sockets to check for read events
|
||||
* @param writeset_in set of sockets to check for write events
|
||||
* @param exceptset_in set of sockets to check for error events
|
||||
* @param readset_out set of sockets that had read events
|
||||
* @param writeset_out set of sockets that had write events
|
||||
* @param exceptset_out set os sockets that had error events
|
||||
* @return number of sockets that had events (read/write/exception) (>= 0)
|
||||
*/
|
||||
static int
|
||||
|
@ -1740,12 +1743,21 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
|||
}
|
||||
|
||||
/* get the IP address and port */
|
||||
/* @todo: this does not work for IPv6, yet */
|
||||
err = netconn_getaddr(sock->conn, &naddr, &port, local);
|
||||
if (err != ERR_OK) {
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */
|
||||
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
|
||||
IP_IS_V4_VAL(naddr)) {
|
||||
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
|
||||
IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||
|
@ -1832,7 +1844,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||
/* write back optlen and optval */
|
||||
*optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
|
||||
#if LWIP_MPU_COMPATIBLE
|
||||
memcpy(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
|
||||
MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
|
||||
LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
|
||||
#endif /* LWIP_MPU_COMPATIBLE */
|
||||
|
||||
|
@ -2022,7 +2034,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
*(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl;
|
||||
*(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
|
||||
s, *(int *)optval));
|
||||
break;
|
||||
|
@ -2031,7 +2043,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
|
||||
inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
|
||||
s, *(u32_t *)optval));
|
||||
break;
|
||||
|
@ -2059,6 +2071,9 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||
case IPPROTO_TCP:
|
||||
/* Special case: all IPPROTO_TCP option take an int */
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
|
||||
if (sock->conn->pcb.tcp->state == LISTEN) {
|
||||
return EINVAL;
|
||||
}
|
||||
switch (optname) {
|
||||
case TCP_NODELAY:
|
||||
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
|
||||
|
@ -2103,10 +2118,6 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||
switch (optname) {
|
||||
case IPV6_V6ONLY:
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
|
||||
/* @todo: this does not work for datagram sockets, yet */
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
*(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
|
||||
s, *(int *)optval));
|
||||
|
@ -2220,7 +2231,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||
LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
|
||||
LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
|
||||
#if LWIP_MPU_COMPATIBLE
|
||||
memcpy(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
|
||||
MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
|
||||
#else /* LWIP_MPU_COMPATIBLE */
|
||||
LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval;
|
||||
#endif /* LWIP_MPU_COMPATIBLE */
|
||||
|
@ -2389,13 +2400,13 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||
#if LWIP_MULTICAST_TX_OPTIONS
|
||||
case IP_MULTICAST_TTL:
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
|
||||
sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval);
|
||||
udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval));
|
||||
break;
|
||||
case IP_MULTICAST_IF:
|
||||
{
|
||||
ip4_addr_t if_addr;
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
|
||||
inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval);
|
||||
inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval);
|
||||
udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
|
||||
}
|
||||
break;
|
||||
|
@ -2419,8 +2430,8 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||
ip4_addr_t if_addr;
|
||||
ip4_addr_t multi_addr;
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
|
||||
inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
|
||||
inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
|
||||
inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
|
||||
inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
|
||||
if (optname == IP_ADD_MEMBERSHIP) {
|
||||
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
|
||||
/* cannot track membership (out of memory) */
|
||||
|
@ -2452,6 +2463,9 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||
case IPPROTO_TCP:
|
||||
/* Special case: all IPPROTO_TCP option take an int */
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
||||
if (sock->conn->pcb.tcp->state == LISTEN) {
|
||||
return EINVAL;
|
||||
}
|
||||
switch (optname) {
|
||||
case TCP_NODELAY:
|
||||
if (*(const int*)optval) {
|
||||
|
@ -2499,7 +2513,6 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||
case IPPROTO_IPV6:
|
||||
switch (optname) {
|
||||
case IPV6_V6ONLY:
|
||||
/* @todo: this does not work for datagram sockets, yet */
|
||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
||||
if (*(const int*)optval) {
|
||||
netconn_set_ipv6only(sock->conn, 1);
|
||||
|
@ -2732,14 +2745,16 @@ lwip_fcntl(int s, int cmd, int val)
|
|||
static int
|
||||
lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
|
||||
{
|
||||
/* s+1 is stored in the array to prevent having to initialize the array
|
||||
(default initialization is to 0) */
|
||||
int sa = s + 1;
|
||||
struct lwip_sock *sock = get_socket(s);
|
||||
int i;
|
||||
|
||||
if (!sock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
|
||||
if (socket_ipv4_multicast_memberships[i].sa == 0) {
|
||||
socket_ipv4_multicast_memberships[i].sa = sa;
|
||||
if (socket_ipv4_multicast_memberships[i].sock == NULL) {
|
||||
socket_ipv4_multicast_memberships[i].sock = sock;
|
||||
ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
|
||||
ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
|
||||
return 1;
|
||||
|
@ -2756,16 +2771,18 @@ lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr
|
|||
static void
|
||||
lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
|
||||
{
|
||||
/* s+1 is stored in the array to prevent having to initialize the array
|
||||
(default initialization is to 0) */
|
||||
int sa = s + 1;
|
||||
struct lwip_sock *sock = get_socket(s);
|
||||
int i;
|
||||
|
||||
if (!sock) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
|
||||
if ((socket_ipv4_multicast_memberships[i].sa == sa) &&
|
||||
if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
|
||||
ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
|
||||
ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
|
||||
socket_ipv4_multicast_memberships[i].sa = 0;
|
||||
socket_ipv4_multicast_memberships[i].sock = NULL;
|
||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
|
||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
|
||||
return;
|
||||
|
@ -2777,25 +2794,26 @@ lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_ad
|
|||
*
|
||||
* ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK).
|
||||
*/
|
||||
static void lwip_socket_drop_registered_memberships(int s)
|
||||
static void
|
||||
lwip_socket_drop_registered_memberships(int s)
|
||||
{
|
||||
/* s+1 is stored in the array to prevent having to initialize the array
|
||||
(default initialization is to 0) */
|
||||
int sa = s + 1;
|
||||
struct lwip_sock *sock = get_socket(s);
|
||||
int i;
|
||||
|
||||
LWIP_ASSERT("socket has no netconn", sockets[s].conn != NULL);
|
||||
if (!sock) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
|
||||
if (socket_ipv4_multicast_memberships[i].sa == sa) {
|
||||
if (socket_ipv4_multicast_memberships[i].sock == sock) {
|
||||
ip_addr_t multi_addr, if_addr;
|
||||
ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
|
||||
ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
|
||||
socket_ipv4_multicast_memberships[i].sa = 0;
|
||||
socket_ipv4_multicast_memberships[i].sock = NULL;
|
||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
|
||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
|
||||
|
||||
netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE);
|
||||
netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "lwip/ip.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "netif/lwip_ethernet.h"
|
||||
|
||||
#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
|
||||
#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
|
||||
|
@ -64,6 +65,13 @@ static sys_mbox_t mbox;
|
|||
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
|
||||
|
@ -90,7 +98,7 @@ tcpip_thread(void *arg)
|
|||
UNLOCK_TCPIP_CORE();
|
||||
LWIP_TCPIP_THREAD_ALIVE();
|
||||
/* wait for a message, timeouts are processed while waiting */
|
||||
sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
|
||||
TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
|
||||
LOCK_TCPIP_CORE();
|
||||
if (msg == NULL) {
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
|
||||
|
@ -118,7 +126,7 @@ tcpip_thread(void *arg)
|
|||
break;
|
||||
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
|
||||
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);
|
||||
|
@ -129,7 +137,7 @@ tcpip_thread(void *arg)
|
|||
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
|
||||
|
||||
case TCPIP_MSG_CALLBACK:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
||||
|
@ -248,11 +256,11 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
|
|||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
|
||||
/**
|
||||
* call sys_timeout in tcpip_thread
|
||||
*
|
||||
* @param msec time in milliseconds for timeout
|
||||
* @param msecs 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
|
||||
|
@ -280,7 +288,6 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|||
/**
|
||||
* 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
|
||||
|
@ -303,7 +310,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
|
|||
sys_mbox_post(&mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
|
||||
|
||||
|
||||
/**
|
||||
|
@ -374,7 +381,7 @@ tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
|
|||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||
|
||||
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
|
||||
|
||||
|
||||
TCPIP_MSG_VAR_ALLOC(msg);
|
||||
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
|
||||
TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
|
||||
|
|
|
@ -98,8 +98,8 @@
|
|||
#include "lwip/ip.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memset */
|
||||
#include <stdlib.h> /* atoi */
|
||||
#include <stdio.h>
|
||||
|
||||
#if LWIP_TCP
|
||||
|
@ -337,82 +337,6 @@ char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each ext
|
|||
static struct http_state *http_connections;
|
||||
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
|
||||
|
||||
#if LWIP_HTTPD_STRNSTR_PRIVATE
|
||||
/** Like strstr but does not need 'buffer' to be NULL-terminated */
|
||||
static char*
|
||||
strnstr(const char* buffer, const char* token, size_t n)
|
||||
{
|
||||
const char* p;
|
||||
int tokenlen = (int)strlen(token);
|
||||
if (tokenlen == 0) {
|
||||
return (char *)(size_t)buffer;
|
||||
}
|
||||
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
|
||||
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
|
||||
return (char *)(size_t)p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* LWIP_HTTPD_STRNSTR_PRIVATE */
|
||||
|
||||
#if LWIP_HTTPD_STRICMP_PRIVATE
|
||||
static int
|
||||
stricmp(const char* str1, const char* str2)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *str1++;
|
||||
c2 = *str2++;
|
||||
if (c1 != c2) {
|
||||
char c1_upc = c1 | 0x20;
|
||||
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
|
||||
/* characters are not equal an one is in the alphabet range:
|
||||
downcase both chars and check again */
|
||||
char c2_upc = c2 | 0x20;
|
||||
if (c1_upc != c2_upc) {
|
||||
/* still not equal */
|
||||
/* don't care for < or > */
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* characters are not equal but none is in the alphabet range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (c1 != 0);
|
||||
return 0;
|
||||
}
|
||||
#endif /* LWIP_HTTPD_STRICMP_PRIVATE */
|
||||
|
||||
#if LWIP_HTTPD_ITOA_PRIVATE && LWIP_HTTPD_DYNAMIC_HEADERS
|
||||
static void
|
||||
httpd_itoa(int value, char* result)
|
||||
{
|
||||
const int base = 10;
|
||||
char* ptr = result, *ptr1 = result, tmp_char;
|
||||
int tmp_value;
|
||||
|
||||
do {
|
||||
tmp_value = value;
|
||||
value /= base;
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
|
||||
} while(value);
|
||||
|
||||
/* Apply negative sign */
|
||||
if (tmp_value < 0) {
|
||||
*ptr++ = '-';
|
||||
}
|
||||
*ptr-- = '\0';
|
||||
while(ptr1 < ptr) {
|
||||
tmp_char = *ptr;
|
||||
*ptr--= *ptr1;
|
||||
*ptr1++ = tmp_char;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
|
||||
static void
|
||||
http_kill_oldest_connection(u8_t ssi_required)
|
||||
|
@ -964,7 +888,7 @@ get_http_headers(struct http_state *hs, const char *uri)
|
|||
/* Now determine the content type and add the relevant header for that. */
|
||||
for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) {
|
||||
/* Have we found a matching extension? */
|
||||
if(!stricmp(g_psHTTPHeaders[content_type].extension, ext)) {
|
||||
if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1012,7 +936,7 @@ get_http_headers(struct http_state *hs, const char *uri)
|
|||
}
|
||||
if (add_content_len) {
|
||||
size_t len;
|
||||
LWIP_HTTPD_ITOA(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
|
||||
lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
|
||||
hs->handle->len);
|
||||
len = strlen(hs->hdr_content_len);
|
||||
if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) {
|
||||
|
@ -1112,7 +1036,7 @@ http_send_headers(struct tcp_pcb *pcb, struct http_state *hs)
|
|||
* (which would happen when sending files from async read). */
|
||||
if(http_check_eof(pcb, hs)) {
|
||||
data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If we get here and there are still header bytes to send, we send
|
||||
* the header information we just wrote immediately. If there are no
|
||||
|
@ -1553,6 +1477,8 @@ http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs)
|
|||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1802,16 +1728,16 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
|
|||
{
|
||||
err_t err;
|
||||
/* search for end-of-header (first double-CRLF) */
|
||||
char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
|
||||
char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
|
||||
|
||||
if (crlfcrlf != NULL) {
|
||||
/* search for "Content-Length: " */
|
||||
#define HTTP_HDR_CONTENT_LEN "Content-Length: "
|
||||
#define HTTP_HDR_CONTENT_LEN_LEN 16
|
||||
#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10
|
||||
char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
|
||||
char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
|
||||
if (scontent_len != NULL) {
|
||||
char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
|
||||
char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
|
||||
if (scontent_len_end != NULL) {
|
||||
int content_len;
|
||||
char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
|
||||
|
@ -1953,7 +1879,7 @@ http_continue(void *connection)
|
|||
* When data has been received in the correct state, try to parse it
|
||||
* as a HTTP request.
|
||||
*
|
||||
* @param p the received pbuf
|
||||
* @param inp the received pbuf
|
||||
* @param hs the connection state
|
||||
* @param pcb the tcp_pcb which received this packet
|
||||
* @return ERR_OK if request was OK and hs has been initialized correctly
|
||||
|
@ -2020,7 +1946,7 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
|
|||
/* received enough data for minimal request? */
|
||||
if (data_len >= MIN_REQ_LEN) {
|
||||
/* wait for CRLF before parsing anything */
|
||||
crlf = strnstr(data, CRLF, data_len);
|
||||
crlf = lwip_strnstr(data, CRLF, data_len);
|
||||
if (crlf != NULL) {
|
||||
#if LWIP_HTTPD_SUPPORT_POST
|
||||
int is_post = 0;
|
||||
|
@ -2052,11 +1978,11 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
|
|||
}
|
||||
/* if we come here, method is OK, parse URI */
|
||||
left_len = (u16_t)(data_len - ((sp1 +1) - data));
|
||||
sp2 = strnstr(sp1 + 1, " ", left_len);
|
||||
sp2 = lwip_strnstr(sp1 + 1, " ", left_len);
|
||||
#if LWIP_HTTPD_SUPPORT_V09
|
||||
if (sp2 == NULL) {
|
||||
/* HTTP 0.9: respond with correct protocol version */
|
||||
sp2 = strnstr(sp1 + 1, CRLF, left_len);
|
||||
sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len);
|
||||
is_09 = 1;
|
||||
#if LWIP_HTTPD_SUPPORT_POST
|
||||
if (is_post) {
|
||||
|
@ -2069,13 +1995,13 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
|
|||
uri_len = (u16_t)(sp2 - (sp1 + 1));
|
||||
if ((sp2 != 0) && (sp2 > sp1)) {
|
||||
/* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */
|
||||
if (strnstr(data, CRLF CRLF, data_len) != NULL) {
|
||||
if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) {
|
||||
char *uri = sp1 + 1;
|
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||
/* This is HTTP/1.0 compatible: for strict 1.1, a connection
|
||||
would always be persistent unless "close" was specified. */
|
||||
if (!is_09 && (strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
|
||||
strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
|
||||
if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
|
||||
lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
|
||||
hs->keepalive = 1;
|
||||
} else {
|
||||
hs->keepalive = 0;
|
||||
|
@ -2259,7 +2185,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
|
|||
}
|
||||
tag_check = 0;
|
||||
for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
|
||||
if (!stricmp(ext, g_pcSSIExtensions[loop])) {
|
||||
if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) {
|
||||
tag_check = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -2285,7 +2211,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
|
|||
* @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
|
||||
* @param uri the HTTP header URI
|
||||
* @param tag_check enable SSI tag checking
|
||||
* @param uri_has_params != NULL if URI has parameters (separated by '?')
|
||||
* @param params != NULL if URI has parameters (separated by '?')
|
||||
* @return ERR_OK if file was found and hs has been initialized correctly
|
||||
* another err_t otherwise
|
||||
*/
|
||||
|
@ -2334,7 +2260,7 @@ http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const cha
|
|||
if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) {
|
||||
/* HTTP/0.9 responses are sent without HTTP header,
|
||||
search for the end of the header. */
|
||||
char *file_start = strnstr(hs->file, CRLF CRLF, hs->left);
|
||||
char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left);
|
||||
if (file_start != NULL) {
|
||||
size_t diff = file_start + 4 - hs->file;
|
||||
hs->file += diff;
|
||||
|
@ -2584,7 +2510,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
LWIP_UNUSED_ARG(err);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg));
|
||||
|
||||
|
||||
if ((err != ERR_OK) || (pcb == NULL)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
@ -2637,6 +2563,7 @@ httpd_init(void)
|
|||
tcp_setprio(pcb, HTTPD_TCP_PRIO);
|
||||
/* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
|
||||
err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
|
||||
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
|
||||
pcb = tcp_listen(pcb);
|
||||
LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
|
||||
|
@ -2684,7 +2611,7 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
|
|||
{
|
||||
LWIP_ASSERT("no cgis given", cgis != NULL);
|
||||
LWIP_ASSERT("invalid number of handlers", num_handlers > 0);
|
||||
|
||||
|
||||
g_pCGIs = cgis;
|
||||
g_iNumCGIs = num_handlers;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* makefsdata: Converts a directory structure for use with the lwIP httpd.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*
|
||||
* Author: Jim Pettinato
|
||||
* Simon Goldschmidt
|
||||
*
|
||||
|
@ -818,7 +818,7 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size,
|
|||
u8_t provide_last_modified = includeLastModified;
|
||||
|
||||
memset(hdr_buf, 0, sizeof(hdr_buf));
|
||||
|
||||
|
||||
if (useHttp11) {
|
||||
response_type = HTTP_HDR_OK_11;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
|
|||
/* this session is time-limited */
|
||||
u32_t now = sys_now();
|
||||
u32_t diff_ms = now - conn->time_started;
|
||||
u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount);
|
||||
u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount);
|
||||
u32_t time_ms = time * 10;
|
||||
if (diff_ms >= time_ms) {
|
||||
/* time specified by the client is over -> close the connection */
|
||||
|
@ -271,7 +271,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
|
|||
}
|
||||
} else {
|
||||
/* this session is byte-limited */
|
||||
u32_t amount_bytes = htonl(conn->settings.amount);
|
||||
u32_t amount_bytes = lwip_htonl(conn->settings.amount);
|
||||
/* @todo: this can send up to 1*MSS more than requested... */
|
||||
if (amount_bytes >= conn->bytes_transferred) {
|
||||
/* all requested bytes transferred -> close the connection */
|
||||
|
@ -294,7 +294,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
|
|||
} else {
|
||||
/* transmit data */
|
||||
/* @todo: every x bytes, transmit the settings again */
|
||||
txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
|
||||
txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
|
||||
txlen_max = TCP_MSS;
|
||||
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
|
||||
txlen_max = TCP_MSS - 24;
|
||||
|
@ -374,7 +374,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn)
|
|||
return ERR_MEM;
|
||||
}
|
||||
|
||||
memcpy(client_conn, conn, sizeof(lwiperf_state_tcp_t));
|
||||
MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t));
|
||||
client_conn->base.server = 0;
|
||||
client_conn->server_pcb = NULL;
|
||||
client_conn->conn_pcb = newpcb;
|
||||
|
@ -390,7 +390,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn)
|
|||
tcp_err(newpcb, lwiperf_tcp_err);
|
||||
|
||||
ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
|
||||
remote_port = (u16_t)htonl(client_conn->settings.remote_port);
|
||||
remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port);
|
||||
|
||||
err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
|
||||
if (err != ERR_OK) {
|
||||
|
@ -405,6 +405,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn)
|
|||
static err_t
|
||||
lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
u8_t tmp;
|
||||
u16_t tot_len;
|
||||
u32_t packet_idx;
|
||||
struct pbuf* q;
|
||||
|
@ -470,8 +471,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
|||
return ERR_OK;
|
||||
}
|
||||
conn->next_num = 4; /* 24 bytes received... */
|
||||
err = pbuf_header(p, -24);
|
||||
LWIP_ASSERT("pbuf_header failed", err == ERR_OK);
|
||||
tmp = pbuf_header(p, -24);
|
||||
LWIP_ASSERT("pbuf_header failed", tmp == 0);
|
||||
}
|
||||
|
||||
packet_idx = 0;
|
||||
|
@ -493,10 +494,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
|||
return ERR_VAL;
|
||||
}
|
||||
}
|
||||
packet_idx += i;
|
||||
#else
|
||||
packet_idx += q->len;
|
||||
#endif
|
||||
packet_idx += q->len;
|
||||
}
|
||||
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
|
||||
conn->bytes_transferred += packet_idx;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -46,6 +46,7 @@
|
|||
|
||||
#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
|
@ -270,7 +271,7 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
/* decode the NetBIOS name */
|
||||
netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
|
||||
/* if the packet is for us */
|
||||
if (NETBIOS_STRCMP(netbios_name, NETBIOS_LOCAL_NAME) == 0) {
|
||||
if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
|
||||
struct pbuf *q;
|
||||
struct netbios_resp *resp;
|
||||
|
||||
|
@ -327,7 +328,7 @@ netbiosns_init(void)
|
|||
netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (netbiosns_pcb != NULL) {
|
||||
/* we have to be allowed to send broadcast packets! */
|
||||
netbiosns_pcb->so_options |= SOF_BROADCAST;
|
||||
ip_set_option(netbiosns_pcb, SOF_BROADCAST);
|
||||
udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
|
||||
udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
|
||||
}
|
||||
|
@ -346,7 +347,7 @@ netbiosns_set_name(const char* hostname)
|
|||
if (copy_len >= NETBIOS_NAME_LEN) {
|
||||
copy_len = NETBIOS_NAME_LEN - 1;
|
||||
}
|
||||
memcpy(netbiosns_local_name, hostname, copy_len + 1);
|
||||
MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
lwIP SNMPv2c agent
|
||||
==================
|
||||
|
||||
Based on SNMP stack written by Christiaan Simons <christiaan.simons@axon.tv>
|
||||
|
||||
Rewritten by Martin Hentschel <info@cl-soft.de> and
|
||||
Dirk Ziegelmeier <dziegel@gmx.de>
|
||||
|
||||
Features:
|
||||
- SNMPv2c support.
|
||||
- Low RAM usage - no memory pools, stack only.
|
||||
- MIB2 implementation is separated from SNMP stack.
|
||||
- Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB.
|
||||
- Simple and generic API for MIB implementation.
|
||||
- Comfortable node types and helper functions for scalar arrays and tables.
|
||||
- Counter64, bit and truthvalue datatype support.
|
||||
- Callbacks for SNMP writes e.g. to implement persistency.
|
||||
- Runs on two APIs: RAW and netconn.
|
||||
- Async API is gone - the stack now supports netconn API instead,
|
||||
so blocking operations can be done in MIB calls.
|
||||
SNMP runs in a worker thread when netconn API is used.
|
||||
- Simplified thread sync support for MIBs - useful when MIBs
|
||||
need to access variables shared with other threads where no locking is
|
||||
possible. Used in MIB2 to access lwIP stats from lwIP thread.
|
||||
|
||||
MIB compiler (code generator):
|
||||
- Written in C#. MIB viewer used Windows Forms.
|
||||
- Developed on Windows with Visual Studio 2010.
|
||||
- Can be compiled and used under Linux with http://www.monodevelop.com/.
|
||||
- Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4)
|
||||
(https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate).
|
||||
- MIB parser, C file generation framework and LWIP code generation are cleanly
|
||||
separated, which means the code may be useful as a base for code generation
|
||||
of other SNMP agents.
|
||||
|
||||
Notes:
|
||||
- Stack and MIB compiler were used to implement a Profinet device.
|
||||
Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB.
|
|
@ -196,10 +196,10 @@ snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, co
|
|||
octets_needed--;
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3))));
|
||||
}
|
||||
|
||||
|
||||
/* skip to low u32 */
|
||||
value++;
|
||||
|
||||
|
||||
while (octets_needed > 1) {
|
||||
octets_needed--;
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3))));
|
||||
|
@ -288,7 +288,7 @@ snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t
|
|||
/**
|
||||
* Returns octet count for length.
|
||||
*
|
||||
* @param length
|
||||
* @param length parameter length
|
||||
* @param octets_needed points to the return value
|
||||
*/
|
||||
void
|
||||
|
@ -306,7 +306,7 @@ snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
|
|||
/**
|
||||
* Returns octet count for an u32_t.
|
||||
*
|
||||
* @param value
|
||||
* @param value value to be encoded
|
||||
* @param octets_needed points to the return value
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||
|
@ -332,7 +332,7 @@ snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
|
|||
/**
|
||||
* Returns octet count for an u64_t.
|
||||
*
|
||||
* @param value
|
||||
* @param value value to be encoded
|
||||
* @param octets_needed points to the return value
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||
|
@ -357,7 +357,7 @@ snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed)
|
|||
/**
|
||||
* Returns octet count for an s32_t.
|
||||
*
|
||||
* @param value
|
||||
* @param value value to be encoded
|
||||
* @param octets_needed points to the return value
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed.
|
||||
|
@ -367,7 +367,7 @@ snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed)
|
|||
{
|
||||
if (value < 0) {
|
||||
value = ~value;
|
||||
}
|
||||
}
|
||||
if (value < 0x80L) {
|
||||
*octets_needed = 1;
|
||||
} else if (value < 0x8000L) {
|
||||
|
@ -453,7 +453,7 @@ snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tl
|
|||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||
tlv->value_len <<= 8;
|
||||
tlv->value_len |= data;
|
||||
|
||||
|
||||
/* take care for special value used for indefinite length */
|
||||
if (tlv->value_len == 0xFFFF) {
|
||||
return ERR_VAL;
|
||||
|
@ -551,7 +551,7 @@ snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value
|
|||
} else {
|
||||
*value <<= 8;
|
||||
}
|
||||
|
||||
|
||||
*value |= data;
|
||||
len--;
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value
|
|||
if ((len > 0) && (len < 5)) {
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||
len--;
|
||||
|
||||
|
||||
if (data & 0x80) {
|
||||
/* negative, start from -1 */
|
||||
*value = -1;
|
||||
|
@ -649,7 +649,7 @@ snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u
|
|||
if (oid_max_len < 2) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||
len--;
|
||||
|
||||
|
@ -736,7 +736,7 @@ snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u1
|
|||
return ERR_MEM;
|
||||
}
|
||||
*buf_len = len;
|
||||
|
||||
|
||||
while (len > 0) {
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf));
|
||||
buf++;
|
||||
|
|
|
@ -42,11 +42,48 @@
|
|||
* The agent implements the most important MIB2 MIBs including IPv6 support
|
||||
* (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version
|
||||
* whithout IPv6 statistics (TODO).\n
|
||||
* Work on SNMPv3 has started, but is not finished.
|
||||
* Rewritten by Martin Hentschel <info@cl-soft.de> and
|
||||
* Dirk Ziegelmeier <dziegel@gmx.de>\n
|
||||
* Work on SNMPv3 has started, but is not finished.\n
|
||||
*
|
||||
* 0 Agent Capabilities
|
||||
* ====================
|
||||
*
|
||||
* Features:
|
||||
* ---------
|
||||
* - SNMPv2c support.
|
||||
* - Low RAM usage - no memory pools, stack only.
|
||||
* - MIB2 implementation is separated from SNMP stack.
|
||||
* - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB.
|
||||
* - Simple and generic API for MIB implementation.
|
||||
* - Comfortable node types and helper functions for scalar arrays and tables.
|
||||
* - Counter64, bit and truthvalue datatype support.
|
||||
* - Callbacks for SNMP writes e.g. to implement persistency.
|
||||
* - Runs on two APIs: RAW and netconn.
|
||||
* - Async API is gone - the stack now supports netconn API instead,
|
||||
* so blocking operations can be done in MIB calls.
|
||||
* SNMP runs in a worker thread when netconn API is used.
|
||||
* - Simplified thread sync support for MIBs - useful when MIBs
|
||||
* need to access variables shared with other threads where no locking is
|
||||
* possible. Used in MIB2 to access lwIP stats from lwIP thread.
|
||||
*
|
||||
* MIB compiler (code generator):
|
||||
* ------------------------------
|
||||
* - Provided in lwIP contrib repository.
|
||||
* - Written in C#. MIB viewer used Windows Forms.
|
||||
* - Developed on Windows with Visual Studio 2010.
|
||||
* - Can be compiled and used on all platforms with http://www.monodevelop.com/.
|
||||
* - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4)
|
||||
* (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate).
|
||||
* - MIB parser, C file generation framework and LWIP code generation are cleanly
|
||||
* separated, which means the code may be useful as a base for code generation
|
||||
* of other SNMP agents.
|
||||
*
|
||||
* Notes:
|
||||
* ------
|
||||
* - Stack and MIB compiler were used to implement a Profinet device.
|
||||
* Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB.
|
||||
*
|
||||
* SNMPv1 per RFC1157 and SNMPv2c per RFC 3416
|
||||
* -------------------------------------------
|
||||
* Note the S in SNMP stands for "Simple". Note that "Simple" is
|
||||
|
@ -233,7 +270,7 @@ snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip)
|
|||
(oid[1] > 0xFF) ||
|
||||
(oid[2] > 0xFF) ||
|
||||
(oid[3] > 0xFF)) {
|
||||
ip4_addr_copy(*ip, *IP4_ADDR_ANY);
|
||||
ip4_addr_copy(*ip, *IP4_ADDR_ANY4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -285,10 +322,10 @@ snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0);
|
||||
ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0);
|
||||
ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0);
|
||||
ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0);
|
||||
ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0);
|
||||
ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0);
|
||||
ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0);
|
||||
ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -322,9 +359,9 @@ snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid)
|
|||
#if LWIP_IPV4 || LWIP_IPV6
|
||||
/**
|
||||
* Convert to InetAddressType+InetAddress+InetPortNumber
|
||||
* @param ip
|
||||
* @param port
|
||||
* @param oid
|
||||
* @param ip IP address
|
||||
* @param port Port
|
||||
* @param oid OID
|
||||
* @return OID length
|
||||
*/
|
||||
u8_t
|
||||
|
@ -335,14 +372,14 @@ snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid)
|
|||
idx = snmp_ip_to_oid(ip, oid);
|
||||
oid[idx] = port;
|
||||
idx++;
|
||||
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to InetAddressType+InetAddress
|
||||
* @param ip
|
||||
* @param oid
|
||||
* @param ip IP address
|
||||
* @param oid OID
|
||||
* @return OID length
|
||||
*/
|
||||
u8_t
|
||||
|
@ -375,9 +412,9 @@ snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid)
|
|||
|
||||
/**
|
||||
* Convert from InetAddressType+InetAddress to ip_addr_t
|
||||
* @param oid
|
||||
* @param oid_len
|
||||
* @param ip
|
||||
* @param oid OID
|
||||
* @param oid_len OID length
|
||||
* @param ip IP address
|
||||
* @return Parsed OID length
|
||||
*/
|
||||
u8_t
|
||||
|
@ -387,7 +424,7 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip)
|
|||
if (oid_len < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (oid[0] == 0) { /* any */
|
||||
/* 1x InetAddressType, 1x OID len */
|
||||
if (oid_len < 2) {
|
||||
|
@ -417,7 +454,7 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip)
|
|||
if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 6;
|
||||
#else /* LWIP_IPV4 */
|
||||
return 0;
|
||||
|
@ -450,17 +487,17 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip)
|
|||
|
||||
/**
|
||||
* Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t
|
||||
* @param oid
|
||||
* @param oid_len
|
||||
* @param ip
|
||||
* @param port
|
||||
* @param oid OID
|
||||
* @param oid_len OID length
|
||||
* @param ip IP address
|
||||
* @param port Port
|
||||
* @return Parsed OID length
|
||||
*/
|
||||
u8_t
|
||||
snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port)
|
||||
{
|
||||
u8_t idx = 0;
|
||||
|
||||
|
||||
/* InetAddressType + InetAddress */
|
||||
idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip);
|
||||
if (idx == 0) {
|
||||
|
@ -483,10 +520,10 @@ snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port)
|
|||
#endif /* LWIP_IPV4 || LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Assign an OID to \struct snmp_obj_id
|
||||
* @param target
|
||||
* @param oid
|
||||
* @param oid_len
|
||||
* Assign an OID to struct snmp_obj_id
|
||||
* @param target Assignment target
|
||||
* @param oid OID
|
||||
* @param oid_len OID length
|
||||
*/
|
||||
void
|
||||
snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
||||
|
@ -501,10 +538,10 @@ snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
|||
}
|
||||
|
||||
/**
|
||||
* Prefix an OID to OID in \struct snmp_obj_id
|
||||
* @param target
|
||||
* @param oid
|
||||
* @param oid_len
|
||||
* Prefix an OID to OID in struct snmp_obj_id
|
||||
* @param target Assignment target to prefix
|
||||
* @param oid OID
|
||||
* @param oid_len OID length
|
||||
*/
|
||||
void
|
||||
snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
||||
|
@ -524,12 +561,12 @@ snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
|||
}
|
||||
|
||||
/**
|
||||
* Combine two OIDs into \struct snmp_obj_id
|
||||
* @param target
|
||||
* @param oid1
|
||||
* @param oid1_len
|
||||
* @param oid2
|
||||
* @param oid2_len
|
||||
* Combine two OIDs into struct snmp_obj_id
|
||||
* @param target Assignmet target
|
||||
* @param oid1 OID 1
|
||||
* @param oid1_len OID 1 length
|
||||
* @param oid2 OID 2
|
||||
* @param oid2_len OID 2 length
|
||||
*/
|
||||
void
|
||||
snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
|
||||
|
@ -539,12 +576,12 @@ snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, c
|
|||
}
|
||||
|
||||
/**
|
||||
* Append OIDs to \struct snmp_obj_id
|
||||
* @param target
|
||||
* @param oid
|
||||
* @param oid_len
|
||||
* Append OIDs to struct snmp_obj_id
|
||||
* @param target Assignment target to append to
|
||||
* @param oid OID
|
||||
* @param oid_len OID length
|
||||
*/
|
||||
void
|
||||
void
|
||||
snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
||||
{
|
||||
LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN);
|
||||
|
@ -557,11 +594,11 @@ snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
|
|||
|
||||
/**
|
||||
* Compare two OIDs
|
||||
* @param oid1
|
||||
* @param oid1_len
|
||||
* @param oid2
|
||||
* @param oid2_len
|
||||
* @return
|
||||
* @param oid1 OID 1
|
||||
* @param oid1_len OID 1 length
|
||||
* @param oid2 OID 2
|
||||
* @param oid2_len OID 2 length
|
||||
* @return -1: OID1<OID2 1: OID1 >OID2 0: equal
|
||||
*/
|
||||
s8_t
|
||||
snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
|
||||
|
@ -592,17 +629,17 @@ snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_
|
|||
}
|
||||
|
||||
/* they are equal */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check of two OIDs are equal
|
||||
* @param oid1
|
||||
* @param oid1_len
|
||||
* @param oid2
|
||||
* @param oid2_len
|
||||
* @return
|
||||
* @param oid1 OID 1
|
||||
* @param oid1_len OID 1 length
|
||||
* @param oid2 OID 2
|
||||
* @param oid2_len OID 2 length
|
||||
* @return 1: equal 0: non-equal
|
||||
*/
|
||||
u8_t
|
||||
snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
|
||||
|
@ -612,7 +649,7 @@ snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_le
|
|||
|
||||
/**
|
||||
* Convert netif to interface index
|
||||
* @param netif
|
||||
* @param netif netif
|
||||
* @return index
|
||||
*/
|
||||
u8_t
|
||||
|
@ -735,7 +772,7 @@ snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node
|
|||
mib = snmp_get_mib_from_oid(oid, oid_len);
|
||||
if (mib != NULL) {
|
||||
u8_t oid_instance_len;
|
||||
|
||||
|
||||
mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len);
|
||||
if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) {
|
||||
/* get instance */
|
||||
|
@ -765,7 +802,7 @@ snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node
|
|||
return result;
|
||||
}
|
||||
|
||||
u8_t
|
||||
u8_t
|
||||
snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance)
|
||||
{
|
||||
const struct snmp_mib *mib;
|
||||
|
@ -791,7 +828,7 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida
|
|||
/* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */
|
||||
while ((mib != NULL) && (mn == NULL)) {
|
||||
u8_t oid_instance_len;
|
||||
|
||||
|
||||
/* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */
|
||||
mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len);
|
||||
if (mn != NULL) {
|
||||
|
@ -844,9 +881,9 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida
|
|||
if (node_instance->release_instance != NULL) {
|
||||
node_instance->release_instance(node_instance);
|
||||
}
|
||||
/*
|
||||
/*
|
||||
the instance itself is not valid, ask for next instance from same node.
|
||||
we don't have to change any variables because node_instance->instance_oid is used as input (starting point)
|
||||
we don't have to change any variables because node_instance->instance_oid is used as input (starting point)
|
||||
as well as output (resulting next OID), so we have to simply call get_next_instance method again
|
||||
*/
|
||||
} else {
|
||||
|
@ -889,7 +926,7 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida
|
|||
}
|
||||
/* else { we found out target node } */
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
there is no further (suitable) node inside this MIB, search for the next MIB with following priority
|
||||
1. search for inner MIB's (whose root is located inside tree of current MIB)
|
||||
2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any
|
||||
|
@ -967,11 +1004,11 @@ snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t o
|
|||
*oid_instance_len = oid_len - oid_offset;
|
||||
return (*node);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct snmp_node*
|
||||
const struct snmp_node*
|
||||
snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret)
|
||||
{
|
||||
u8_t oid_offset = mib->base_oid_len;
|
||||
|
@ -1062,7 +1099,7 @@ snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oi
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1140,7 @@ snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, cons
|
|||
}
|
||||
|
||||
/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */
|
||||
u8_t
|
||||
u8_t
|
||||
snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference)
|
||||
{
|
||||
/* do not overwrite a fail result */
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
|
||||
|
||||
static s16_t
|
||||
static s16_t
|
||||
interfaces_get_value(struct snmp_node_instance* instance, void* value)
|
||||
{
|
||||
if (instance->node->oid == 1) {
|
||||
|
@ -131,7 +131,7 @@ interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id*
|
|||
u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
|
||||
|
||||
LWIP_UNUSED_ARG(column);
|
||||
|
||||
|
||||
/* init struct to search next oid */
|
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges));
|
||||
|
||||
|
@ -289,11 +289,10 @@ interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *
|
|||
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
|
||||
LWIP_UNUSED_ARG(len);
|
||||
|
||||
if (*sint_ptr == 1 || *sint_ptr == 2)
|
||||
{
|
||||
if (*sint_ptr == 1 || *sint_ptr == 2) {
|
||||
return SNMP_ERR_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
return SNMP_ERR_WRONGVALUE;
|
||||
}
|
||||
|
||||
|
@ -352,17 +351,17 @@ static const struct snmp_table_col_def interfaces_Table_columns[] = {
|
|||
|
||||
#if !SNMP_SAFE_REQUESTS
|
||||
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
|
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value);
|
||||
#else
|
||||
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
|
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
interfaces_Table_get_value, NULL, NULL);
|
||||
#endif
|
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
|
||||
CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#if LWIP_IPV4
|
||||
/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */
|
||||
|
||||
static s16_t
|
||||
static s16_t
|
||||
ip_get_value(struct snmp_node_instance* instance, void* value)
|
||||
{
|
||||
s32_t* sint_ptr = (s32_t*)value;
|
||||
|
@ -146,7 +146,7 @@ ip_get_value(struct snmp_node_instance* instance, void* value)
|
|||
/**
|
||||
* Test ip object value before setting.
|
||||
*
|
||||
* @param od is the object definition
|
||||
* @param instance node instance
|
||||
* @param len return value space (in bytes)
|
||||
* @param value points to (varbind) space to copy value from.
|
||||
*
|
||||
|
@ -304,7 +304,7 @@ ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_o
|
|||
/* fill in object properties */
|
||||
return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len);
|
||||
}
|
||||
|
||||
|
||||
/* not found */
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const
|
|||
case 1: /* ipRouteDest */
|
||||
if (default_route) {
|
||||
/* default rte has 0.0.0.0 dest */
|
||||
value->u32 = IP4_ADDR_ANY->addr;
|
||||
value->u32 = IP4_ADDR_ANY4->addr;
|
||||
} else {
|
||||
/* netifs have netaddress dest */
|
||||
ip4_addr_t tmp;
|
||||
|
@ -378,7 +378,7 @@ ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const
|
|||
case 11: /* ipRouteMask */
|
||||
if (default_route) {
|
||||
/* default rte use 0.0.0.0 mask */
|
||||
value->u32 = IP4_ADDR_ANY->addr;
|
||||
value->u32 = IP4_ADDR_ANY4->addr;
|
||||
} else {
|
||||
/* other rtes use netmask */
|
||||
value->u32 = netif_ip4_netmask(netif)->addr;
|
||||
|
@ -449,7 +449,7 @@ ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_
|
|||
|
||||
/* check default route */
|
||||
if (netif_default != NULL) {
|
||||
snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[0]);
|
||||
snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]);
|
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default);
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_
|
|||
snmp_ip4_to_oid(&dst, &test_oid[0]);
|
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif);
|
||||
}
|
||||
|
||||
|
||||
netif = netif->next;
|
||||
}
|
||||
|
||||
|
@ -581,7 +581,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||
snmp_ip4_to_oid(ip, &test_oid[1]);
|
||||
|
||||
/* check generated OID: is it a candidate for the next one? */
|
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i);
|
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), LWIP_PTR_NUMERIC_CAST(void*, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,7 +589,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
||||
/* fill in object properties */
|
||||
return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len);
|
||||
return ip_NetToMediaTable_get_cell_value_core(LWIP_PTR_NUMERIC_CAST(u8_t, state.reference), column, value, value_len);
|
||||
}
|
||||
|
||||
/* not found */
|
||||
|
@ -660,7 +660,7 @@ static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREAT
|
|||
#endif /* LWIP_ARP && LWIP_IPV4 */
|
||||
|
||||
#if LWIP_IPV4
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding)
|
||||
CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL)
|
||||
CREATE_LWIP_SYNC_NODE( 3, ip_InReceives)
|
||||
|
@ -730,7 +730,7 @@ static const struct snmp_table_simple_col_def at_Table_columns[] = {
|
|||
|
||||
static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
|
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE(1, at_Table)
|
||||
|
||||
static const struct snmp_node* const at_nodes[] = {
|
||||
|
|
|
@ -188,7 +188,7 @@ snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *v
|
|||
return SNMP_ERR_NOERROR;
|
||||
}
|
||||
|
||||
/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */
|
||||
/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */
|
||||
static const struct snmp_scalar_array_node_def snmp_nodes[] = {
|
||||
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */
|
||||
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */
|
||||
|
|
|
@ -106,7 +106,7 @@ snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len)
|
|||
* Initializes sysContact pointers
|
||||
*
|
||||
* @param ocstr if non-NULL then copy str pointer
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated.
|
||||
* @param bufsize size of the buffer in bytes.
|
||||
* (this is required because the buffer can be overwritten by snmp-set)
|
||||
|
@ -148,7 +148,7 @@ snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
|
|||
* Initializes sysName pointers
|
||||
*
|
||||
* @param ocstr if non-NULL then copy str pointer
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated.
|
||||
* @param bufsize size of the buffer in bytes.
|
||||
* (this is required because the buffer can be overwritten by snmp-set)
|
||||
|
@ -189,7 +189,7 @@ snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
|
|||
* Initializes sysLocation pointers
|
||||
*
|
||||
* @param ocstr if non-NULL then copy str pointer
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated.
|
||||
* @param bufsize size of the buffer in bytes.
|
||||
* (this is required because the buffer can be overwritten by snmp-set)
|
||||
|
@ -278,7 +278,7 @@ system_get_value(const struct snmp_scalar_array_node_def *node, void *value)
|
|||
return result;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
|
||||
{
|
||||
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
|
||||
|
@ -324,7 +324,7 @@ system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *
|
|||
return ret;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
|
||||
{
|
||||
u8_t* var_wr = NULL;
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */
|
||||
|
||||
static s16_t
|
||||
static s16_t
|
||||
tcp_get_value(struct snmp_node_instance* instance, void* value)
|
||||
{
|
||||
u32_t *uint_ptr = (u32_t*)value;
|
||||
|
@ -154,7 +154,7 @@ static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = {
|
|||
{ 0, 0xffff } /* Port */
|
||||
};
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
|
||||
{
|
||||
LWIP_UNUSED_ARG(value_len);
|
||||
|
@ -172,7 +172,7 @@ tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, unio
|
|||
break;
|
||||
case 4: /* tcpConnRemAddress */
|
||||
if (pcb->state == LISTEN) {
|
||||
value->u32 = IP4_ADDR_ANY->addr;
|
||||
value->u32 = IP4_ADDR_ANY4->addr;
|
||||
} else {
|
||||
value->u32 = ip_2_ip4(&pcb->remote_ip)->addr;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row
|
|||
local_port = (u16_t)row_oid[4];
|
||||
snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */
|
||||
remote_port = (u16_t)row_oid[9];
|
||||
|
||||
|
||||
/* find tcp_pcb with requested ips and ports */
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
|
||||
pcb = *tcp_pcb_lists[i];
|
||||
|
@ -224,7 +224,7 @@ tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row
|
|||
|
||||
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
|
||||
if (pcb->state == LISTEN) {
|
||||
if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY) && (remote_port == 0)) {
|
||||
if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) {
|
||||
/* fill in object properties */
|
||||
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
|
||||
}
|
||||
|
@ -261,14 +261,14 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_
|
|||
pcb = *tcp_pcb_lists[i];
|
||||
while (pcb != NULL) {
|
||||
u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
|
||||
|
||||
|
||||
if (IP_IS_V4_VAL(pcb->local_ip)) {
|
||||
snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
|
||||
test_oid[4] = pcb->local_port;
|
||||
|
||||
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
|
||||
if (pcb->state == LISTEN) {
|
||||
snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[5]);
|
||||
snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]);
|
||||
test_oid[9] = 0;
|
||||
} else {
|
||||
if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */
|
||||
|
@ -281,7 +281,7 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_
|
|||
/* check generated OID: is it a candidate for the next one? */
|
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb);
|
||||
}
|
||||
|
||||
|
||||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
|
@ -301,10 +301,10 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_
|
|||
|
||||
/* --- tcpConnectionTable --- */
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value)
|
||||
{
|
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
switch (*column) {
|
||||
case 7: /* tcpConnectionState */
|
||||
value->u32 = pcb->state + 1;
|
||||
|
@ -336,7 +336,7 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8
|
|||
if (idx == 0) {
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
}
|
||||
|
||||
|
||||
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
|
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
|
||||
if (idx == 0) {
|
||||
|
@ -346,7 +346,7 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8
|
|||
/* find tcp_pcb with requested ip and port*/
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
|
||||
pcb = *tcp_pcb_nonlisten_lists[i];
|
||||
|
||||
|
||||
while (pcb != NULL) {
|
||||
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
|
||||
(local_port == pcb->local_port) &&
|
||||
|
@ -358,9 +358,9 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8
|
|||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* not found */
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
|
@ -395,11 +395,11 @@ tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||
|
||||
/* check generated OID: is it a candidate for the next one? */
|
||||
snmp_next_oid_check(&state, test_oid, idx, pcb);
|
||||
|
||||
|
||||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* did we find a next one? */
|
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
||||
|
@ -413,10 +413,10 @@ tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||
|
||||
/* --- tcpListenerTable --- */
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
|
||||
{
|
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
switch (*column) {
|
||||
case 4: /* tcpListenerProcess */
|
||||
value->u32 = 0; /* not supported */
|
||||
|
@ -443,7 +443,7 @@ tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t
|
|||
if (idx == 0) {
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
}
|
||||
|
||||
|
||||
/* find tcp_pcb with requested ip and port*/
|
||||
pcb = tcp_listen_pcbs.listen_pcbs;
|
||||
while (pcb != NULL) {
|
||||
|
@ -456,7 +456,7 @@ tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t
|
|||
}
|
||||
|
||||
/* not found */
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
|
@ -477,13 +477,13 @@ tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct s
|
|||
while (pcb != NULL) {
|
||||
u8_t idx = 0;
|
||||
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
|
||||
|
||||
|
||||
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
|
||||
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
|
||||
|
||||
/* check generated OID: is it a candidate for the next one? */
|
||||
snmp_next_oid_check(&state, test_oid, idx, NULL);
|
||||
|
||||
|
||||
pcb = pcb->next;
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIM
|
|||
#endif /* LWIP_IPV4 */
|
||||
|
||||
static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = {
|
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */
|
||||
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */
|
||||
};
|
||||
|
@ -537,13 +537,13 @@ static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREA
|
|||
|
||||
|
||||
static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = {
|
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
{ 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */
|
||||
};
|
||||
|
||||
static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value);
|
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm)
|
||||
CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin)
|
||||
CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax)
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */
|
||||
|
||||
static s16_t
|
||||
static s16_t
|
||||
udp_get_value(struct snmp_node_instance* instance, void* value)
|
||||
{
|
||||
u32_t *uint_ptr = (u32_t*)value;
|
||||
|
@ -91,10 +91,10 @@ udp_get_value(struct snmp_node_instance* instance, void* value)
|
|||
|
||||
/* --- udpEndpointTable --- */
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
|
||||
{
|
||||
/* all items except udpEndpointProcess are declared as not-accessible */
|
||||
/* all items except udpEndpointProcess are declared as not-accessible */
|
||||
switch (*column) {
|
||||
case 8: /* udpEndpointProcess */
|
||||
value->u32 = 0; /* not supported */
|
||||
|
@ -106,7 +106,7 @@ udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_va
|
|||
return SNMP_ERR_NOERROR;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
static snmp_err_t
|
||||
udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
|
||||
{
|
||||
ip_addr_t local_ip, remote_ip;
|
||||
|
|
|
@ -125,6 +125,7 @@ snmp_get_community_trap(void)
|
|||
void
|
||||
snmp_set_community_write(const char * const community)
|
||||
{
|
||||
LWIP_ASSERT("community string must not be NULL", community != NULL);
|
||||
LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
|
||||
snmp_community_write = community;
|
||||
}
|
||||
|
@ -272,8 +273,7 @@ snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t
|
|||
}
|
||||
}
|
||||
|
||||
if (request->error_status != SNMP_ERR_NOERROR)
|
||||
{
|
||||
if (request->error_status != SNMP_ERR_NOERROR) {
|
||||
if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
|
||||
if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) {
|
||||
/* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */
|
||||
|
@ -323,7 +323,7 @@ snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t
|
|||
/**
|
||||
* Service an internal or external event for SNMP GET.
|
||||
*
|
||||
* @param msg_ps points to the associated message process state
|
||||
* @param request points to the associated message process state
|
||||
*/
|
||||
static err_t
|
||||
snmp_process_get_request(struct snmp_request *request)
|
||||
|
@ -359,7 +359,7 @@ snmp_process_get_request(struct snmp_request *request)
|
|||
/**
|
||||
* Service an internal or external event for SNMP GET.
|
||||
*
|
||||
* @param msg_ps points to the associated message process state
|
||||
* @param request points to the associated message process state
|
||||
*/
|
||||
static err_t
|
||||
snmp_process_getnext_request(struct snmp_request *request)
|
||||
|
@ -395,7 +395,7 @@ snmp_process_getnext_request(struct snmp_request *request)
|
|||
/**
|
||||
* Service an internal or external event for SNMP GETBULKT.
|
||||
*
|
||||
* @param msg_ps points to the associated message process state
|
||||
* @param request points to the associated message process state
|
||||
*/
|
||||
static err_t
|
||||
snmp_process_getbulk_request(struct snmp_request *request)
|
||||
|
@ -493,7 +493,7 @@ snmp_process_getbulk_request(struct snmp_request *request)
|
|||
/**
|
||||
* Service an internal or external event for SNMP SET.
|
||||
*
|
||||
* @param msg_ps points to the associated message process state
|
||||
* @param request points to the associated message process state
|
||||
*/
|
||||
static err_t
|
||||
snmp_process_set_request(struct snmp_request *request)
|
||||
|
@ -512,8 +512,7 @@ snmp_process_set_request(struct snmp_request *request)
|
|||
memset(&node_instance, 0, sizeof(node_instance));
|
||||
|
||||
request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
|
||||
if (request->error_status == SNMP_ERR_NOERROR)
|
||||
{
|
||||
if (request->error_status == SNMP_ERR_NOERROR) {
|
||||
if (node_instance.asn1_type != vb.type) {
|
||||
request->error_status = SNMP_ERR_WRONGTYPE;
|
||||
} else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) {
|
||||
|
@ -528,8 +527,7 @@ snmp_process_set_request(struct snmp_request *request)
|
|||
node_instance.release_instance(&node_instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
|
||||
} else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
|
||||
/* no more varbinds in request */
|
||||
break;
|
||||
} else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) {
|
||||
|
@ -551,10 +549,8 @@ snmp_process_set_request(struct snmp_request *request)
|
|||
struct snmp_node_instance node_instance;
|
||||
memset(&node_instance, 0, sizeof(node_instance));
|
||||
request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
|
||||
if (request->error_status == SNMP_ERR_NOERROR)
|
||||
{
|
||||
if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR)
|
||||
{
|
||||
if (request->error_status == SNMP_ERR_NOERROR) {
|
||||
if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) {
|
||||
if (request->inbound_varbind_enumerator.varbind_count == 1) {
|
||||
request->error_status = SNMP_ERR_COMMITFAILED;
|
||||
} else {
|
||||
|
@ -650,11 +646,12 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
#if LWIP_SNMP_V3
|
||||
if (request->version == SNMP_VERSION_3) {
|
||||
u16_t u16_value;
|
||||
u16_t inbound_msgAuthenticationParameters_offset;
|
||||
|
||||
/* SNMPv3 doesn't use communities */
|
||||
/* @todo: Differentiate read/write access */
|
||||
strcpy((char*)request->community, snmp_community);
|
||||
request->community_strlen = strlen(snmp_community);
|
||||
request->community_strlen = (u16_t)strlen(snmp_community);
|
||||
|
||||
/* RFC3414 globalData */
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
|
||||
|
@ -687,7 +684,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
IF_PARSE_ASSERT(parent_tlv_value_len > 0);
|
||||
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
|
||||
request->msg_flags = s32_value;
|
||||
request->msg_flags = (u8_t)s32_value;
|
||||
|
||||
/* decode msgSecurityModel */
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
|
||||
|
@ -724,7 +721,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id,
|
||||
&u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
|
||||
request->msg_authoritative_engine_id_len = u16_value;
|
||||
request->msg_authoritative_engine_id_len = (u8_t)u16_value;
|
||||
|
||||
/* msgAuthoritativeEngineBoots */
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
|
||||
|
@ -749,7 +746,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name,
|
||||
&u16_value, SNMP_V3_MAX_USER_LENGTH));
|
||||
request->msg_user_name_len = u16_value;
|
||||
request->msg_user_name_len = (u8_t)u16_value;
|
||||
/* @todo: Implement unknown user error response */
|
||||
IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL));
|
||||
|
||||
|
@ -760,7 +757,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
|
||||
IF_PARSE_ASSERT(parent_tlv_value_len > 0);
|
||||
/* Remember position */
|
||||
u16_t inbound_msgAuthenticationParameters_offset = pbuf_stream.offset;
|
||||
inbound_msgAuthenticationParameters_offset = pbuf_stream.offset;
|
||||
LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset);
|
||||
/* Read auth parameters */
|
||||
IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH);
|
||||
|
@ -769,18 +766,19 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
|
||||
#if LWIP_SNMP_V3_CRYPTO
|
||||
if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
|
||||
/* Rewind stream */
|
||||
IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
|
||||
IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset));
|
||||
/* Set auth parameters to zero for verification */
|
||||
const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 };
|
||||
IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len));
|
||||
|
||||
/* Verify authentication */
|
||||
u8_t key[20];
|
||||
u8_t algo;
|
||||
u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)];
|
||||
struct snmp_pbuf_stream auth_stream;
|
||||
|
||||
/* Rewind stream */
|
||||
IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
|
||||
IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset));
|
||||
/* Set auth parameters to zero for verification */
|
||||
IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len));
|
||||
|
||||
/* Verify authentication */
|
||||
IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
|
||||
|
||||
IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL));
|
||||
|
@ -839,7 +837,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id,
|
||||
&u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
|
||||
request->context_engine_id_len = u16_value;
|
||||
request->context_engine_id_len = (u8_t)u16_value;
|
||||
|
||||
/* contextName */
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
|
||||
|
@ -849,7 +847,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
|
||||
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name,
|
||||
&u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
|
||||
request->context_name_len = u16_value;
|
||||
request->context_name_len = (u8_t)u16_value;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@ -913,7 +911,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|||
snmp_authfail_trap();
|
||||
return ERR_ARG;
|
||||
} else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
|
||||
if (strnlen(snmp_community_write, SNMP_MAX_COMMUNITY_STR_LEN) == 0) {
|
||||
if (snmp_community_write[0] == 0) {
|
||||
/* our write community is empty, that means all our objects are readonly */
|
||||
request->error_status = SNMP_ERR_NOTWRITABLE;
|
||||
request->error_index = 1;
|
||||
|
@ -1065,7 +1063,7 @@ snmp_prepare_outbound_frame(struct snmp_request *request)
|
|||
|
||||
/* msgAuthoritativeEngineID */
|
||||
snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len);
|
||||
memcpy(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len);
|
||||
MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len);
|
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len);
|
||||
OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
|
||||
OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len));
|
||||
|
@ -1140,7 +1138,7 @@ snmp_prepare_outbound_frame(struct snmp_request *request)
|
|||
|
||||
/* contextEngineID */
|
||||
snmpv3_get_engine_id(&id, &request->context_engine_id_len);
|
||||
memcpy(request->context_engine_id, id, request->context_engine_id_len);
|
||||
MEMCPY(request->context_engine_id, id, request->context_engine_id_len);
|
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len);
|
||||
OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
|
||||
OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len));
|
||||
|
@ -1361,6 +1359,19 @@ snmp_complete_outbound_frame(struct snmp_request *request)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
|
||||
/* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */
|
||||
switch (request->error_status) {
|
||||
case SNMP_ERR_NOSUCHINSTANCE:
|
||||
case SNMP_ERR_NOSUCHOBJECT:
|
||||
case SNMP_ERR_ENDOFMIBVIEW:
|
||||
request->error_status = SNMP_ERR_NOTWRITABLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
|
||||
/* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */
|
||||
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
|
||||
|
@ -1382,7 +1393,7 @@ snmp_complete_outbound_frame(struct snmp_request *request)
|
|||
/* Calculate padding for encryption */
|
||||
if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
|
||||
u8_t i;
|
||||
outbound_padding = (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x03);
|
||||
outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07;
|
||||
for (i = 0; i < outbound_padding; i++) {
|
||||
snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0);
|
||||
}
|
||||
|
@ -1517,7 +1528,7 @@ snmp_complete_outbound_frame(struct snmp_request *request)
|
|||
request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
|
||||
OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac));
|
||||
|
||||
memcpy(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
|
||||
MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
|
||||
OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream,
|
||||
request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
|
||||
OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream,
|
||||
|
@ -1547,7 +1558,7 @@ snmp_execute_write_callbacks(struct snmp_request *request)
|
|||
snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
|
||||
vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */
|
||||
|
||||
while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == ERR_OK) {
|
||||
while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) {
|
||||
snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#if LWIP_SNMP && SNMP_USE_NETCONN
|
||||
|
||||
#include <string.h>
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/udp.h"
|
||||
|
@ -52,12 +53,12 @@ snmp_netconn_thread(void *arg)
|
|||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
/* Bind to SNMP port with default IP address */
|
||||
#if LWIP_IPV6
|
||||
#if LWIP_IPV6
|
||||
conn = netconn_new(NETCONN_UDP_IPV6);
|
||||
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT);
|
||||
#else /* LWIP_IPV6 */
|
||||
conn = netconn_new(NETCONN_UDP);
|
||||
netconn_bind(conn, IP_ADDR_ANY, SNMP_IN_PORT);
|
||||
netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT);
|
||||
#endif /* LWIP_IPV6 */
|
||||
LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;);
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result)
|
|||
/**
|
||||
* @ingroup snmp_core
|
||||
* Starts SNMP Agent.
|
||||
* Allocates UDP pcb and binds it to IP_ADDR_ANY port 161.
|
||||
* Allocates UDP pcb and binds it to IP_ANY_TYPE port 161.
|
||||
*/
|
||||
void
|
||||
snmp_init(void)
|
||||
|
|
|
@ -211,6 +211,7 @@ void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_thread
|
|||
err_t err = sys_mutex_new(&instance->sem_usage_mutex);
|
||||
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
|
||||
err = sys_sem_new(&instance->sem, 0);
|
||||
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
|
||||
instance->sync_fn = sync_fn;
|
||||
}
|
||||
|
|
|
@ -147,11 +147,13 @@ snmp_get_auth_traps_enabled(void)
|
|||
|
||||
|
||||
/**
|
||||
* Sends an generic or enterprise specific trap message.
|
||||
* @ingroup snmp_traps
|
||||
* Sends a generic or enterprise specific trap message.
|
||||
*
|
||||
* @param generic_trap is the trap code
|
||||
* @param eoid points to enterprise object identifier
|
||||
* @param generic_trap is the trap code
|
||||
* @param specific_trap used for enterprise traps when generic_trap == 6
|
||||
* @param varbinds linked list of varbinds to be sent
|
||||
* @return ERR_OK when success, ERR_MEM if we're out of memory
|
||||
*
|
||||
* @note the use of the enterprise identifier field
|
||||
|
@ -160,8 +162,8 @@ snmp_get_auth_traps_enabled(void)
|
|||
* and .iso.org.dod.internet.private.enterprises.yourenterprise
|
||||
* (sysObjectID) for specific traps.
|
||||
*/
|
||||
static err_t
|
||||
snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds)
|
||||
err_t
|
||||
snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds)
|
||||
{
|
||||
struct snmp_msg_trap trap_msg;
|
||||
struct snmp_trap_dst *td;
|
||||
|
@ -175,10 +177,10 @@ snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_tr
|
|||
if ((td->enable != 0) && !ip_addr_isany(&td->dip)) {
|
||||
/* lookup current source address for this dst */
|
||||
if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) {
|
||||
if (device_enterprise_oid == NULL) {
|
||||
if (eoid == NULL) {
|
||||
trap_msg.enterprise = snmp_get_device_enterprise_oid();
|
||||
} else {
|
||||
trap_msg.enterprise = device_enterprise_oid;
|
||||
trap_msg.enterprise = eoid;
|
||||
}
|
||||
|
||||
trap_msg.gen_trap = generic_trap;
|
||||
|
@ -224,7 +226,7 @@ snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_tr
|
|||
|
||||
/**
|
||||
* @ingroup snmp_traps
|
||||
* Send generic SNMP trap
|
||||
* Send generic SNMP trap
|
||||
*/
|
||||
err_t
|
||||
snmp_send_trap_generic(s32_t generic_trap)
|
||||
|
@ -234,7 +236,7 @@ snmp_send_trap_generic(s32_t generic_trap)
|
|||
}
|
||||
|
||||
/**
|
||||
*@ingroup snmp_traps
|
||||
* @ingroup snmp_traps
|
||||
* Send specific SNMP trap with variable bindings
|
||||
*/
|
||||
err_t
|
||||
|
@ -295,8 +297,8 @@ snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds)
|
|||
* Sums trap header field lengths from tail to head and
|
||||
* returns trap_header_lengths for second encoding pass.
|
||||
*
|
||||
* @param trap Trap message
|
||||
* @param vb_len varbind-list length
|
||||
* @param thl points to returned header lengths
|
||||
* @return the required length for encoding the trap header
|
||||
*/
|
||||
static u16_t
|
||||
|
|
|
@ -114,8 +114,8 @@ snmpv3_build_priv_param(u8_t* priv_param)
|
|||
priv2 = LWIP_RAND();
|
||||
}
|
||||
|
||||
memcpy(&priv_param[0], &priv1, sizeof(priv1));
|
||||
memcpy(&priv_param[4], &priv2, sizeof(priv2));
|
||||
SMEMCPY(&priv_param[0], &priv1, sizeof(priv1));
|
||||
SMEMCPY(&priv_param[4], &priv2, sizeof(priv2));
|
||||
|
||||
/* Emulate 64bit increment */
|
||||
priv1++;
|
||||
|
@ -125,8 +125,8 @@ snmpv3_build_priv_param(u8_t* priv_param)
|
|||
#else /* Based on RFC3414 */
|
||||
static u32_t ctr;
|
||||
u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS();
|
||||
memcpy(&priv_param[0], &boots, 4);
|
||||
memcpy(&priv_param[4], &ctr, 4);
|
||||
SMEMCPY(&priv_param[0], &boots, 4);
|
||||
SMEMCPY(&priv_param[4], &ctr, 4);
|
||||
ctr++;
|
||||
#endif
|
||||
return ERR_OK;
|
||||
|
|
|
@ -192,7 +192,7 @@ snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length,
|
|||
iv_local[4 + 1] = (engine_time >> 16) & 0xFF;
|
||||
iv_local[4 + 2] = (engine_time >> 8) & 0xFF;
|
||||
iv_local[4 + 3] = (engine_time >> 0) & 0xFF;
|
||||
memcpy(iv_local + 8, priv_param, 8);
|
||||
SMEMCPY(iv_local + 8, priv_param, 8);
|
||||
if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -263,9 +263,9 @@ snmpv3_password_to_key_md5(
|
|||
/* May want to ensure that engineLength <= 32, */
|
||||
/* otherwise need to use a buffer larger than 64 */
|
||||
/*****************************************************/
|
||||
memcpy(password_buf, key, 16);
|
||||
memcpy(password_buf + 16, engineID, engineLength);
|
||||
memcpy(password_buf + 16 + engineLength, key, 16);
|
||||
SMEMCPY(password_buf, key, 16);
|
||||
MEMCPY(password_buf + 16, engineID, engineLength);
|
||||
SMEMCPY(password_buf + 16 + engineLength, key, 16);
|
||||
|
||||
mbedtls_md5_starts(&MD);
|
||||
mbedtls_md5_update(&MD, password_buf, 32 + engineLength);
|
||||
|
@ -316,9 +316,9 @@ snmpv3_password_to_key_sha(
|
|||
/* May want to ensure that engineLength <= 32, */
|
||||
/* otherwise need to use a buffer larger than 72 */
|
||||
/*****************************************************/
|
||||
memcpy(password_buf, key, 20);
|
||||
memcpy(password_buf + 20, engineID, engineLength);
|
||||
memcpy(password_buf + 20 + engineLength, key, 20);
|
||||
SMEMCPY(password_buf, key, 20);
|
||||
MEMCPY(password_buf + 20, engineID, engineLength);
|
||||
SMEMCPY(password_buf + 20 + engineLength, key, 20);
|
||||
|
||||
mbedtls_sha1_starts(&SH);
|
||||
mbedtls_sha1_update(&SH, password_buf, 40 + engineLength);
|
||||
|
|
|
@ -79,11 +79,12 @@ struct snmp_varbind_enumerator
|
|||
u16_t varbind_count;
|
||||
};
|
||||
|
||||
typedef u8_t snmp_vb_enumerator_err_t;
|
||||
#define SNMP_VB_ENUMERATOR_ERR_OK 0
|
||||
#define SNMP_VB_ENUMERATOR_ERR_EOVB 1
|
||||
#define SNMP_VB_ENUMERATOR_ERR_ASN1ERROR 2
|
||||
#define SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH 3
|
||||
typedef enum {
|
||||
SNMP_VB_ENUMERATOR_ERR_OK = 0,
|
||||
SNMP_VB_ENUMERATOR_ERR_EOVB = 1,
|
||||
SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2,
|
||||
SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3
|
||||
} snmp_vb_enumerator_err_t;
|
||||
|
||||
void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length);
|
||||
snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind);
|
||||
|
|
|
@ -212,13 +212,13 @@ 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]);
|
||||
u32_t rx_secs = lwip_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;
|
||||
u32_t us = lwip_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));
|
||||
|
@ -247,10 +247,10 @@ sntp_initialize_request(struct sntp_msg *req)
|
|||
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);
|
||||
sntp_last_timestamp_sent[0] = lwip_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);
|
||||
sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us);
|
||||
req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
|
||||
}
|
||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
||||
|
@ -573,6 +573,7 @@ sntp_stop(void)
|
|||
{
|
||||
if (sntp_pcb != NULL) {
|
||||
sys_untimeout(sntp_request, NULL);
|
||||
sys_untimeout(sntp_try_next_server, NULL);
|
||||
udp_remove(sntp_pcb);
|
||||
sntp_pcb = NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
/****************************************************************//**
|
||||
*
|
||||
* @file tftp_server.c
|
||||
*
|
||||
* @author Logan Gunthorpe <logang@deltatee.com>
|
||||
* Dirk Ziegelmeier <dziegel@gmx.de>
|
||||
*
|
||||
* @brief Trivial File Transfer Protocol (RFC 1350)
|
||||
*
|
||||
* Copyright (c) Deltatee Enterprises Ltd. 2013
|
||||
* 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: Logan Gunthorpe <logang@deltatee.com>
|
||||
* Dirk Ziegelmeier <dziegel@gmx.de>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tftp TFTP server
|
||||
* @ingroup apps
|
||||
*
|
||||
* This is simple TFTP server for the lwIP raw API.
|
||||
*/
|
||||
|
||||
#include "lwip/apps/tftp_server.h"
|
||||
|
||||
#if LWIP_UDP
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "lwip/debug.h"
|
||||
|
||||
#define TFTP_MAX_PAYLOAD_SIZE 512
|
||||
#define TFTP_HEADER_LENGTH 4
|
||||
|
||||
#define TFTP_RRQ 1
|
||||
#define TFTP_WRQ 2
|
||||
#define TFTP_DATA 3
|
||||
#define TFTP_ACK 4
|
||||
#define TFTP_ERROR 5
|
||||
|
||||
enum tftp_error {
|
||||
TFTP_ERROR_FILE_NOT_FOUND = 1,
|
||||
TFTP_ERROR_ACCESS_VIOLATION = 2,
|
||||
TFTP_ERROR_DISK_FULL = 3,
|
||||
TFTP_ERROR_ILLEGAL_OPERATION = 4,
|
||||
TFTP_ERROR_UNKNOWN_TRFR_ID = 5,
|
||||
TFTP_ERROR_FILE_EXISTS = 6,
|
||||
TFTP_ERROR_NO_SUCH_USER = 7
|
||||
};
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct tftp_state {
|
||||
const struct tftp_context *ctx;
|
||||
void *handle;
|
||||
struct pbuf *last_data;
|
||||
struct udp_pcb *upcb;
|
||||
ip_addr_t addr;
|
||||
u16_t port;
|
||||
int timer;
|
||||
int last_pkt;
|
||||
u16_t blknum;
|
||||
u8_t retries;
|
||||
u8_t mode_write;
|
||||
};
|
||||
|
||||
static struct tftp_state tftp_state;
|
||||
|
||||
static void tftp_tmr(void* arg);
|
||||
|
||||
static void
|
||||
close_handle(void)
|
||||
{
|
||||
tftp_state.port = 0;
|
||||
ip_addr_set_any(0, &tftp_state.addr);
|
||||
|
||||
if(tftp_state.last_data != NULL) {
|
||||
pbuf_free(tftp_state.last_data);
|
||||
tftp_state.last_data = NULL;
|
||||
}
|
||||
|
||||
sys_untimeout(tftp_tmr, NULL);
|
||||
|
||||
if (tftp_state.handle) {
|
||||
tftp_state.ctx->close(tftp_state.handle);
|
||||
tftp_state.handle = NULL;
|
||||
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n"));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str)
|
||||
{
|
||||
int str_length = strlen(str);
|
||||
struct pbuf* p;
|
||||
u16_t* payload;
|
||||
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM);
|
||||
if(p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
payload = (u16_t*) p->payload;
|
||||
payload[0] = PP_HTONS(TFTP_ERROR);
|
||||
payload[1] = lwip_htons(code);
|
||||
MEMCPY(&payload[2], str, str_length + 1);
|
||||
|
||||
udp_sendto(tftp_state.upcb, p, addr, port);
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
send_ack(u16_t blknum)
|
||||
{
|
||||
struct pbuf* p;
|
||||
u16_t* payload;
|
||||
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM);
|
||||
if(p == NULL) {
|
||||
return;
|
||||
}
|
||||
payload = (u16_t*) p->payload;
|
||||
|
||||
payload[0] = PP_HTONS(TFTP_ACK);
|
||||
payload[1] = lwip_htons(blknum);
|
||||
udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port);
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
resend_data(void)
|
||||
{
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM);
|
||||
if(p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port);
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
send_data(void)
|
||||
{
|
||||
u16_t *payload;
|
||||
int ret;
|
||||
|
||||
if(tftp_state.last_data != NULL) {
|
||||
pbuf_free(tftp_state.last_data);
|
||||
}
|
||||
|
||||
tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM);
|
||||
if(tftp_state.last_data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
payload = (u16_t *) tftp_state.last_data->payload;
|
||||
payload[0] = PP_HTONS(TFTP_DATA);
|
||||
payload[1] = lwip_htons(tftp_state.blknum);
|
||||
|
||||
ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE);
|
||||
if (ret < 0) {
|
||||
send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file.");
|
||||
close_handle();
|
||||
return;
|
||||
}
|
||||
|
||||
pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret));
|
||||
resend_data();
|
||||
}
|
||||
|
||||
static void
|
||||
recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
u16_t *sbuf = (u16_t *) p->payload;
|
||||
int opcode;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(upcb);
|
||||
|
||||
if (((tftp_state.port != 0) && (port != tftp_state.port)) ||
|
||||
(!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
opcode = sbuf[0];
|
||||
|
||||
tftp_state.last_pkt = tftp_state.timer;
|
||||
tftp_state.retries = 0;
|
||||
|
||||
switch (opcode) {
|
||||
case PP_HTONS(TFTP_RRQ): /* fall through */
|
||||
case PP_HTONS(TFTP_WRQ):
|
||||
{
|
||||
const char tftp_null = 0;
|
||||
char filename[TFTP_MAX_FILENAME_LEN];
|
||||
char mode[TFTP_MAX_MODE_LEN];
|
||||
u16_t filename_end_offset;
|
||||
u16_t mode_end_offset;
|
||||
|
||||
if(tftp_state.handle != NULL) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
|
||||
|
||||
/* find \0 in pbuf -> end of filename string */
|
||||
filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2);
|
||||
if((u16_t)(filename_end_offset-2) > sizeof(filename)) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated");
|
||||
break;
|
||||
}
|
||||
pbuf_copy_partial(p, filename, filename_end_offset-2, 2);
|
||||
|
||||
/* find \0 in pbuf -> end of mode string */
|
||||
mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1);
|
||||
if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated");
|
||||
break;
|
||||
}
|
||||
pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1);
|
||||
|
||||
tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ));
|
||||
tftp_state.blknum = 1;
|
||||
|
||||
if (!tftp_state.handle) {
|
||||
send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file.");
|
||||
break;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read"));
|
||||
ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr);
|
||||
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode));
|
||||
|
||||
ip_addr_copy(tftp_state.addr, *addr);
|
||||
tftp_state.port = port;
|
||||
|
||||
if (opcode == PP_HTONS(TFTP_WRQ)) {
|
||||
tftp_state.mode_write = 1;
|
||||
send_ack(0);
|
||||
} else {
|
||||
tftp_state.mode_write = 0;
|
||||
send_data();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PP_HTONS(TFTP_DATA):
|
||||
{
|
||||
int ret;
|
||||
u16_t blknum;
|
||||
|
||||
if (tftp_state.handle == NULL) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
|
||||
break;
|
||||
}
|
||||
|
||||
if (tftp_state.mode_write != 1) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection");
|
||||
break;
|
||||
}
|
||||
|
||||
blknum = lwip_ntohs(sbuf[1]);
|
||||
pbuf_header(p, -TFTP_HEADER_LENGTH);
|
||||
|
||||
ret = tftp_state.ctx->write(tftp_state.handle, p);
|
||||
if (ret < 0) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file");
|
||||
close_handle();
|
||||
} else {
|
||||
send_ack(blknum);
|
||||
}
|
||||
|
||||
if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) {
|
||||
close_handle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PP_HTONS(TFTP_ACK):
|
||||
{
|
||||
u16_t blknum;
|
||||
int lastpkt;
|
||||
|
||||
if (tftp_state.handle == NULL) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
|
||||
break;
|
||||
}
|
||||
|
||||
if (tftp_state.mode_write != 0) {
|
||||
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection");
|
||||
break;
|
||||
}
|
||||
|
||||
blknum = lwip_ntohs(sbuf[1]);
|
||||
if (blknum != tftp_state.blknum) {
|
||||
send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number");
|
||||
break;
|
||||
}
|
||||
|
||||
lastpkt = 0;
|
||||
|
||||
if (tftp_state.last_data != NULL) {
|
||||
lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
if (!lastpkt) {
|
||||
tftp_state.blknum++;
|
||||
send_data();
|
||||
} else {
|
||||
close_handle();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation");
|
||||
break;
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
tftp_tmr(void* arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
tftp_state.timer++;
|
||||
|
||||
if (tftp_state.handle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
|
||||
|
||||
if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) {
|
||||
if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) {
|
||||
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n"));
|
||||
resend_data();
|
||||
tftp_state.retries++;
|
||||
} else {
|
||||
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n"));
|
||||
close_handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @ingroup tftp
|
||||
* Initialize TFTP server.
|
||||
* @param ctx TFTP callback struct
|
||||
*/
|
||||
err_t
|
||||
tftp_init(const struct tftp_context *ctx)
|
||||
{
|
||||
err_t ret;
|
||||
|
||||
struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (pcb == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT);
|
||||
if (ret != ERR_OK) {
|
||||
udp_remove(pcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tftp_state.handle = NULL;
|
||||
tftp_state.port = 0;
|
||||
tftp_state.ctx = ctx;
|
||||
tftp_state.timer = 0;
|
||||
tftp_state.last_data = NULL;
|
||||
tftp_state.upcb = pcb;
|
||||
|
||||
udp_recv(pcb, recv, NULL);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* LWIP_UDP */
|
|
@ -2,6 +2,28 @@
|
|||
* @file
|
||||
* AutoIP Automatic LinkLocal IP Configuration
|
||||
*
|
||||
* This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
|
||||
* with RFC 3927.
|
||||
*
|
||||
* @defgroup autoip AUTOIP
|
||||
* @ingroup ip4
|
||||
* AUTOIP related functions
|
||||
* USAGE:
|
||||
*
|
||||
* define @ref LWIP_AUTOIP 1 in your lwipopts.h
|
||||
* Options:
|
||||
* AUTOIP_TMR_INTERVAL msecs,
|
||||
* 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 @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
|
||||
* - Configure your DHCP Client.
|
||||
*
|
||||
* @see netifapi_autoip
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -32,41 +54,6 @@
|
|||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup autoip AUTOIP
|
||||
* @ingroup ip4
|
||||
* AUTOIP related functions
|
||||
* @see netifapi_autoip
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
@ -79,35 +66,10 @@
|
|||
#include "lwip/netif.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/prot/autoip.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)
|
||||
|
||||
/* 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 10 /* (max conflicts before rate limiting) */
|
||||
#define RATE_LIMIT_INTERVAL 60 /* 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
|
||||
|
||||
/** 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
|
||||
|
@ -115,7 +77,7 @@
|
|||
((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))
|
||||
(netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0))
|
||||
#endif /* LWIP_AUTOIP_RAND */
|
||||
|
||||
/**
|
||||
|
@ -124,7 +86,7 @@
|
|||
*/
|
||||
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
|
||||
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
|
||||
htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
|
||||
lwip_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 */
|
||||
|
||||
|
@ -132,7 +94,6 @@
|
|||
static err_t autoip_arp_announce(struct netif *netif);
|
||||
static void autoip_start_probing(struct netif *netif);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup autoip
|
||||
* Set a statically allocated struct autoip to work with.
|
||||
|
@ -146,12 +107,13 @@ 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);
|
||||
LWIP_ASSERT("netif already has a struct autoip set",
|
||||
netif_autoip_data(netif) == NULL);
|
||||
|
||||
/* clear data structure */
|
||||
memset(autoip, 0, sizeof(struct autoip));
|
||||
/* autoip->state = AUTOIP_STATE_OFF; */
|
||||
netif->autoip = autoip;
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
|
||||
}
|
||||
|
||||
/** Restart AutoIP client and check the next address (conflict detected)
|
||||
|
@ -161,7 +123,8 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip)
|
|||
static void
|
||||
autoip_restart(struct netif *netif)
|
||||
{
|
||||
netif->autoip->tried_llipaddr++;
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
autoip->tried_llipaddr++;
|
||||
autoip_start(netif);
|
||||
}
|
||||
|
||||
|
@ -171,6 +134,8 @@ autoip_restart(struct netif *netif)
|
|||
static void
|
||||
autoip_handle_arp_conflict(struct netif *netif)
|
||||
{
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
/* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where
|
||||
a) means retreat on the first conflict and
|
||||
b) allows to keep an already configured address when having only one
|
||||
|
@ -178,7 +143,7 @@ autoip_handle_arp_conflict(struct netif *netif)
|
|||
We use option b) since it helps to improve the chance that one of the two
|
||||
conflicting hosts may be able to retain its address. */
|
||||
|
||||
if (netif->autoip->lastconflict > 0) {
|
||||
if (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"));
|
||||
|
@ -189,7 +154,7 @@ autoip_handle_arp_conflict(struct netif *netif)
|
|||
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;
|
||||
autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,12 +167,14 @@ autoip_handle_arp_conflict(struct netif *netif)
|
|||
static void
|
||||
autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
|
||||
{
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
/* 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;
|
||||
u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
|
||||
addr += autoip->tried_llipaddr;
|
||||
addr = AUTOIP_NET | (addr & 0xffff);
|
||||
/* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
|
||||
|
||||
|
@ -219,11 +186,11 @@ autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
|
|||
}
|
||||
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
ip4_addr_set_u32(ipaddr, htonl(addr));
|
||||
ip4_addr_set_u32(ipaddr, lwip_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),
|
||||
(u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
|
||||
ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
||||
}
|
||||
|
||||
|
@ -235,8 +202,9 @@ autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
|
|||
static err_t
|
||||
autoip_arp_probe(struct netif *netif)
|
||||
{
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
/* this works because netif->ip_addr is ANY */
|
||||
return etharp_request(netif, &netif->autoip->llipaddr);
|
||||
return etharp_request(netif, &autoip->llipaddr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,7 +226,7 @@ autoip_arp_announce(struct netif *netif)
|
|||
static err_t
|
||||
autoip_bind(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
ip4_addr_t sn_mask, gw_addr;
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
|
@ -285,7 +253,7 @@ autoip_bind(struct netif *netif)
|
|||
err_t
|
||||
autoip_start(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
err_t result = ERR_OK;
|
||||
|
||||
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
|
||||
|
@ -293,7 +261,7 @@ autoip_start(struct netif *netif)
|
|||
/* 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);
|
||||
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
|
||||
|
@ -310,7 +278,7 @@ autoip_start(struct netif *netif)
|
|||
}
|
||||
memset(autoip, 0, sizeof(struct autoip));
|
||||
/* store this AutoIP client in the netif */
|
||||
netif->autoip = autoip;
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
|
||||
} else {
|
||||
autoip->state = AUTOIP_STATE_OFF;
|
||||
|
@ -329,14 +297,14 @@ autoip_start(struct netif *netif)
|
|||
static void
|
||||
autoip_start_probing(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
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)));
|
||||
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
|
||||
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
|
||||
|
||||
/* time to wait to first probe, this is randomly
|
||||
* chosen out of 0 to PROBE_WAIT seconds.
|
||||
|
@ -363,7 +331,9 @@ autoip_start_probing(struct netif *netif)
|
|||
void
|
||||
autoip_network_changed(struct netif *netif)
|
||||
{
|
||||
if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
if (autoip && (autoip->state != AUTOIP_STATE_OFF)) {
|
||||
autoip_start_probing(netif);
|
||||
}
|
||||
}
|
||||
|
@ -377,10 +347,12 @@ autoip_network_changed(struct netif *netif)
|
|||
err_t
|
||||
autoip_stop(struct netif *netif)
|
||||
{
|
||||
if (netif->autoip) {
|
||||
netif->autoip->state = AUTOIP_STATE_OFF;
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
if (autoip != NULL) {
|
||||
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);
|
||||
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
|
@ -395,45 +367,46 @@ autoip_tmr(void)
|
|||
struct netif *netif = netif_list;
|
||||
/* loop through netif's */
|
||||
while (netif != NULL) {
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
/* only act on AutoIP configured interfaces */
|
||||
if (netif->autoip != NULL) {
|
||||
if (netif->autoip->lastconflict > 0) {
|
||||
netif->autoip->lastconflict--;
|
||||
if (autoip != NULL) {
|
||||
if (autoip->lastconflict > 0) {
|
||||
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));
|
||||
(u16_t)(autoip->state), autoip->ttw));
|
||||
|
||||
if (netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
if (autoip->ttw > 0) {
|
||||
autoip->ttw--;
|
||||
}
|
||||
|
||||
switch(netif->autoip->state) {
|
||||
switch(autoip->state) {
|
||||
case AUTOIP_STATE_PROBING:
|
||||
if (netif->autoip->ttw == 0) {
|
||||
if (netif->autoip->sent_num >= PROBE_NUM) {
|
||||
if (autoip->ttw == 0) {
|
||||
if (autoip->sent_num >= PROBE_NUM) {
|
||||
/* Switch to ANNOUNCING: now we can bind to an IP address and use it */
|
||||
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||
autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||
autoip_bind(netif);
|
||||
/* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP
|
||||
which counts as an announcement */
|
||||
netif->autoip->sent_num = 1;
|
||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
autoip->sent_num = 1;
|
||||
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)));
|
||||
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
|
||||
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
|
||||
} else {
|
||||
autoip_arp_probe(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n"));
|
||||
netif->autoip->sent_num++;
|
||||
if (netif->autoip->sent_num == PROBE_NUM) {
|
||||
autoip->sent_num++;
|
||||
if (autoip->sent_num == PROBE_NUM) {
|
||||
/* calculate time to wait to for announce */
|
||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
} else {
|
||||
/* calculate time to wait to next probe */
|
||||
netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
|
||||
autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
|
||||
((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
|
||||
PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
|
||||
}
|
||||
|
@ -442,20 +415,20 @@ autoip_tmr(void)
|
|||
break;
|
||||
|
||||
case AUTOIP_STATE_ANNOUNCING:
|
||||
if (netif->autoip->ttw == 0) {
|
||||
if (autoip->ttw == 0) {
|
||||
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++;
|
||||
autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
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;
|
||||
if (autoip->sent_num >= ANNOUNCE_NUM) {
|
||||
autoip->state = AUTOIP_STATE_BOUND;
|
||||
autoip->sent_num = 0;
|
||||
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)));
|
||||
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
|
||||
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -471,7 +444,7 @@ autoip_tmr(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* Handles every incoming ARP Packet, called by etharp_arp_input.
|
||||
* Handles every incoming ARP Packet, called by etharp_input().
|
||||
*
|
||||
* @param netif network interface to use for autoip processing
|
||||
* @param hdr Incoming ARP packet
|
||||
|
@ -479,8 +452,10 @@ autoip_tmr(void)
|
|||
void
|
||||
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
{
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
|
||||
if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
|
||||
if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) {
|
||||
/* when ip.src == llipaddr && hw.src != netif->hwaddr
|
||||
*
|
||||
* when probing ip.dst == llipaddr && hw.src != netif->hwaddr
|
||||
|
@ -496,15 +471,16 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||
IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
|
||||
IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
|
||||
|
||||
if (netif->autoip->state == AUTOIP_STATE_PROBING) {
|
||||
if (autoip->state == AUTOIP_STATE_PROBING) {
|
||||
/* 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) &&
|
||||
if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
|
||||
(ip4_addr_isany_val(sipaddr) &&
|
||||
ip4_addr_cmp(&dipaddr, &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"));
|
||||
|
@ -515,7 +491,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||
* in any state we have a conflict if
|
||||
* ip.src == llipaddr && hw.src != own hwaddr
|
||||
*/
|
||||
if (ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
|
||||
if (ip4_addr_cmp(&sipaddr, &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"));
|
||||
|
@ -534,13 +510,18 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||
u8_t
|
||||
autoip_supplied_address(const struct netif *netif)
|
||||
{
|
||||
if ((netif != NULL) && (netif->autoip != NULL)) {
|
||||
if ((netif->autoip->state == AUTOIP_STATE_BOUND) ||
|
||||
(netif->autoip->state == AUTOIP_STATE_ANNOUNCING)) {
|
||||
return 1;
|
||||
}
|
||||
if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) {
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8_t
|
||||
autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr)
|
||||
{
|
||||
struct autoip* autoip = netif_autoip_data(netif);
|
||||
return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr));
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV4 && LWIP_AUTOIP */
|
||||
|
|
|
@ -2,6 +2,26 @@
|
|||
* @file
|
||||
* Dynamic Host Configuration Protocol client
|
||||
*
|
||||
* @defgroup dhcp4 DHCPv4
|
||||
* @ingroup ip4
|
||||
* DHCP (IPv4) related functions
|
||||
* This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
|
||||
* with RFC 2131 and RFC 2132.
|
||||
*
|
||||
* @todo:
|
||||
* - Support for interfaces other than Ethernet (SLIP, PPP, ...)
|
||||
*
|
||||
* Options:
|
||||
* @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
|
||||
* @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
|
||||
*
|
||||
* dhcp_start() starts a DHCP client instance which
|
||||
* configures the interface by obtaining an IP address lease and maintaining it.
|
||||
*
|
||||
* Use dhcp_release() to end the lease and use dhcp_stop()
|
||||
* to remove the DHCP client.
|
||||
*
|
||||
* @see netifapi_dhcp4
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -38,38 +58,6 @@
|
|||
*
|
||||
* Author: Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
*
|
||||
* This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
|
||||
* with RFC 2131 and RFC 2132.
|
||||
*
|
||||
* @todo:
|
||||
* - Support for interfaces other than Ethernet (SLIP, PPP, ...)
|
||||
*
|
||||
* Please coordinate changes and requests with Leon Woestenberg
|
||||
* <leon.woestenberg@gmx.net>
|
||||
*
|
||||
* Integration with your code:
|
||||
*
|
||||
* In lwip/dhcp.h
|
||||
* #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
|
||||
* #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
|
||||
*
|
||||
* Then have your application call dhcp_coarse_tmr() and
|
||||
* dhcp_fine_tmr() on the defined intervals.
|
||||
*
|
||||
* dhcp_start(struct netif *netif);
|
||||
* starts a DHCP client instance which configures the interface by
|
||||
* obtaining an IP address lease and maintaining it.
|
||||
*
|
||||
* Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
|
||||
* to remove the DHCP client.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup dhcp4 DHCPv4
|
||||
* @ingroup ip4
|
||||
* DHCP (IPv4) related functions
|
||||
* @see netifapi_dhcp4
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
@ -86,6 +74,7 @@
|
|||
#include "lwip/autoip.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/prot/dhcp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -114,26 +103,40 @@
|
|||
|
||||
#define REBOOT_TRIES 2
|
||||
|
||||
#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
|
||||
#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
|
||||
#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
|
||||
#else
|
||||
#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
|
||||
#endif
|
||||
#else
|
||||
#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
|
||||
#endif
|
||||
|
||||
/** Option handling: options are parsed in dhcp_parse_reply
|
||||
* and saved in an array where other functions can load them from.
|
||||
* This might be moved into the struct dhcp (not necessarily since
|
||||
* lwIP is single-threaded and the array is only used while in recv
|
||||
* callback). */
|
||||
#define DHCP_OPTION_IDX_OVERLOAD 0
|
||||
#define DHCP_OPTION_IDX_MSG_TYPE 1
|
||||
#define DHCP_OPTION_IDX_SERVER_ID 2
|
||||
#define DHCP_OPTION_IDX_LEASE_TIME 3
|
||||
#define DHCP_OPTION_IDX_T1 4
|
||||
#define DHCP_OPTION_IDX_T2 5
|
||||
#define DHCP_OPTION_IDX_SUBNET_MASK 6
|
||||
#define DHCP_OPTION_IDX_ROUTER 7
|
||||
#define DHCP_OPTION_IDX_DNS_SERVER 8
|
||||
enum dhcp_option_idx {
|
||||
DHCP_OPTION_IDX_OVERLOAD = 0,
|
||||
DHCP_OPTION_IDX_MSG_TYPE,
|
||||
DHCP_OPTION_IDX_SERVER_ID,
|
||||
DHCP_OPTION_IDX_LEASE_TIME,
|
||||
DHCP_OPTION_IDX_T1,
|
||||
DHCP_OPTION_IDX_T2,
|
||||
DHCP_OPTION_IDX_SUBNET_MASK,
|
||||
DHCP_OPTION_IDX_ROUTER,
|
||||
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||
DHCP_OPTION_IDX_DNS_SERVER,
|
||||
DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
|
||||
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||
#if LWIP_DHCP_GET_NTP_SRV
|
||||
#define DHCP_OPTION_IDX_NTP_SERVER (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
||||
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS)
|
||||
#else /* LWIP_DHCP_GET_NTP_SRV */
|
||||
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
||||
DHCP_OPTION_IDX_NTP_SERVER,
|
||||
DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
|
||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||
DHCP_OPTION_IDX_MAX
|
||||
};
|
||||
|
||||
/** Holds the decoded option values, only valid while in dhcp_recv.
|
||||
@todo: move this into struct dhcp? */
|
||||
|
@ -146,8 +149,10 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
|
|||
static u8_t dhcp_discover_request_options[] = {
|
||||
DHCP_OPTION_SUBNET_MASK,
|
||||
DHCP_OPTION_ROUTER,
|
||||
DHCP_OPTION_BROADCAST,
|
||||
DHCP_OPTION_DNS_SERVER
|
||||
DHCP_OPTION_BROADCAST
|
||||
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||
, DHCP_OPTION_DNS_SERVER
|
||||
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||
#if LWIP_DHCP_GET_NTP_SRV
|
||||
, DHCP_OPTION_NTP
|
||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||
|
@ -221,13 +226,13 @@ dhcp_inc_pcb_refcount(void)
|
|||
ip_set_option(dhcp_pcb, SOF_BROADCAST);
|
||||
|
||||
/* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
|
||||
udp_bind(dhcp_pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp_pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
udp_recv(dhcp_pcb, dhcp_recv, NULL);
|
||||
udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
udp_recv(dhcp_pcb, dhcp_recv, NULL);
|
||||
}
|
||||
|
||||
dhcp_pcb_refcount++;
|
||||
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
@ -237,7 +242,7 @@ dhcp_dec_pcb_refcount(void)
|
|||
{
|
||||
LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0));
|
||||
dhcp_pcb_refcount--;
|
||||
|
||||
|
||||
if (dhcp_pcb_refcount == 0) {
|
||||
udp_remove(dhcp_pcb);
|
||||
dhcp_pcb = NULL;
|
||||
|
@ -259,14 +264,15 @@ dhcp_dec_pcb_refcount(void)
|
|||
static void
|
||||
dhcp_handle_nak(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
/* Change to a defined state - set this before assigning the address
|
||||
to ensure the callback can use dhcp_supplied_address() */
|
||||
dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
|
||||
/* remove IP address from interface (must no longer be used, as per RFC2131) */
|
||||
netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
|
||||
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
|
||||
/* We can immediately restart discovery */
|
||||
dhcp_discover(netif);
|
||||
}
|
||||
|
@ -284,7 +290,7 @@ dhcp_handle_nak(struct netif *netif)
|
|||
static void
|
||||
dhcp_check(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||
|
@ -313,12 +319,13 @@ dhcp_check(struct netif *netif)
|
|||
static void
|
||||
dhcp_handle_offer(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
/* obtain the server address */
|
||||
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
|
||||
ip_addr_set_ip4_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
|
||||
ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
|
||||
ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
|
||||
/* remember offered address */
|
||||
|
@ -344,7 +351,7 @@ dhcp_handle_offer(struct netif *netif)
|
|||
static err_t
|
||||
dhcp_select(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
u8_t i;
|
||||
|
@ -360,10 +367,10 @@ dhcp_select(struct netif *netif)
|
|||
|
||||
/* MUST request the offered IP address */
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
|
||||
|
@ -379,7 +386,7 @@ dhcp_select(struct netif *netif)
|
|||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* send broadcast to any DHCP server */
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
|
||||
} else {
|
||||
|
@ -396,6 +403,7 @@ dhcp_select(struct netif *netif)
|
|||
|
||||
/**
|
||||
* The DHCP timer that checks for lease renewal/rebind timeouts.
|
||||
* Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS).
|
||||
*/
|
||||
void
|
||||
dhcp_coarse_tmr(void)
|
||||
|
@ -405,7 +413,7 @@ dhcp_coarse_tmr(void)
|
|||
/* iterate through all network interfaces */
|
||||
while (netif != NULL) {
|
||||
/* only act on DHCP configured interfaces */
|
||||
struct dhcp* dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) {
|
||||
/* compare lease time to expire timeout */
|
||||
if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) {
|
||||
|
@ -431,7 +439,8 @@ dhcp_coarse_tmr(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* DHCP transaction timeout handling
|
||||
* DHCP transaction timeout handling (this function must be called every 500ms,
|
||||
* see @ref DHCP_FINE_TIMER_MSECS).
|
||||
*
|
||||
* A DHCP server is expected to respond within a short period of time.
|
||||
* This timer checks whether an outstanding DHCP request is timed out.
|
||||
|
@ -442,14 +451,15 @@ dhcp_fine_tmr(void)
|
|||
struct netif *netif = netif_list;
|
||||
/* loop through netif's */
|
||||
while (netif != NULL) {
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
/* only act on DHCP configured interfaces */
|
||||
if (netif->dhcp != NULL) {
|
||||
if (dhcp != NULL) {
|
||||
/* timer is active (non zero), and is about to trigger now */
|
||||
if (netif->dhcp->request_timeout > 1) {
|
||||
netif->dhcp->request_timeout--;
|
||||
if (dhcp->request_timeout > 1) {
|
||||
dhcp->request_timeout--;
|
||||
}
|
||||
else if (netif->dhcp->request_timeout == 1) {
|
||||
netif->dhcp->request_timeout--;
|
||||
else if (dhcp->request_timeout == 1) {
|
||||
dhcp->request_timeout--;
|
||||
/* { netif->dhcp->request_timeout == 0 } */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
|
||||
/* this client's request timeout triggered */
|
||||
|
@ -472,7 +482,8 @@ dhcp_fine_tmr(void)
|
|||
static void
|
||||
dhcp_timeout(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
|
||||
/* back-off period has passed, or server selection timed out */
|
||||
if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) {
|
||||
|
@ -518,7 +529,8 @@ dhcp_timeout(struct netif *netif)
|
|||
static void
|
||||
dhcp_t1_timeout(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
|
||||
if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
|
||||
(dhcp->state == DHCP_STATE_RENEWING)) {
|
||||
|
@ -530,9 +542,9 @@ dhcp_t1_timeout(struct netif *netif)
|
|||
DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
|
||||
dhcp_renew(netif);
|
||||
/* Calculate next timeout */
|
||||
if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
{
|
||||
netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2);
|
||||
dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -545,7 +557,8 @@ dhcp_t1_timeout(struct netif *netif)
|
|||
static void
|
||||
dhcp_t2_timeout(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
|
||||
if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
|
||||
(dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) {
|
||||
|
@ -556,9 +569,9 @@ dhcp_t2_timeout(struct netif *netif)
|
|||
DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
|
||||
dhcp_rebind(netif);
|
||||
/* Calculate next timeout */
|
||||
if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
{
|
||||
netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2);
|
||||
dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -571,10 +584,11 @@ dhcp_t2_timeout(struct netif *netif)
|
|||
static void
|
||||
dhcp_handle_ack(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
#if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
|
||||
u8_t n;
|
||||
#endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */
|
||||
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
|
||||
#if LWIP_DHCP_GET_NTP_SRV
|
||||
ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
|
||||
#endif
|
||||
|
@ -615,13 +629,13 @@ dhcp_handle_ack(struct netif *netif)
|
|||
#if LWIP_DHCP_BOOTP_FILE
|
||||
/* copy boot server address,
|
||||
boot file name copied in dhcp_parse_reply if not overloaded */
|
||||
ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
|
||||
ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
|
||||
#endif /* LWIP_DHCP_BOOTP_FILE */
|
||||
|
||||
/* subnet mask given? */
|
||||
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
|
||||
/* remember given subnet mask */
|
||||
ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
|
||||
ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
|
||||
dhcp->subnet_mask_given = 1;
|
||||
} else {
|
||||
dhcp->subnet_mask_given = 0;
|
||||
|
@ -629,25 +643,25 @@ dhcp_handle_ack(struct netif *netif)
|
|||
|
||||
/* gateway router */
|
||||
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
|
||||
ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
|
||||
ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
|
||||
}
|
||||
|
||||
#if LWIP_DHCP_GET_NTP_SRV
|
||||
/* NTP servers */
|
||||
for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) {
|
||||
ip4_addr_set_u32(&ntp_server_addrs[n], htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
|
||||
ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
|
||||
}
|
||||
dhcp_set_ntp_servers(n, ntp_server_addrs);
|
||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||
|
||||
#if LWIP_DNS
|
||||
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||
/* DNS servers */
|
||||
for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
|
||||
for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
|
||||
ip_addr_t dns_addr;
|
||||
ip_addr_set_ip4_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
|
||||
ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
|
||||
dns_setserver(n, &dns_addr);
|
||||
}
|
||||
#endif /* LWIP_DNS */
|
||||
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -663,12 +677,12 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
|
|||
{
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
|
||||
LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL);
|
||||
LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL);
|
||||
|
||||
/* clear data structure */
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
|
||||
netif->dhcp = dhcp;
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -684,9 +698,9 @@ void dhcp_cleanup(struct netif *netif)
|
|||
{
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
|
||||
if (netif->dhcp != NULL) {
|
||||
mem_free(netif->dhcp);
|
||||
netif->dhcp = NULL;
|
||||
if (netif_dhcp_data(netif) != NULL) {
|
||||
mem_free(netif_dhcp_data(netif));
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,7 +725,7 @@ dhcp_start(struct netif *netif)
|
|||
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
|
||||
dhcp = netif->dhcp;
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
|
||||
/* check MTU of the netif */
|
||||
|
@ -728,9 +742,9 @@ dhcp_start(struct netif *netif)
|
|||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
|
||||
/* store this dhcp client in the netif */
|
||||
netif->dhcp = dhcp;
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||
/* already has DHCP client attached */
|
||||
} else {
|
||||
|
@ -748,7 +762,7 @@ dhcp_start(struct netif *netif)
|
|||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
|
||||
if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
|
||||
return ERR_MEM;
|
||||
|
@ -810,7 +824,7 @@ dhcp_inform(struct netif *netif)
|
|||
pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
|
||||
|
||||
|
||||
udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
|
||||
dhcp_delete_msg(&dhcp);
|
||||
|
@ -829,7 +843,8 @@ dhcp_inform(struct netif *netif)
|
|||
void
|
||||
dhcp_network_changed(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
|
||||
if (!dhcp)
|
||||
return;
|
||||
switch (dhcp->state) {
|
||||
|
@ -862,7 +877,8 @@ dhcp_network_changed(struct netif *netif)
|
|||
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
/**
|
||||
* Match an ARP reply with the offered IP address.
|
||||
* Match an ARP reply with the offered IP address:
|
||||
* check whether the offered IP address is not in use using ARP
|
||||
*
|
||||
* @param netif the network interface on which the reply was received
|
||||
* @param addr The IP address we received a reply from
|
||||
|
@ -870,15 +886,18 @@ dhcp_network_changed(struct netif *netif)
|
|||
void
|
||||
dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
|
||||
{
|
||||
struct dhcp *dhcp;
|
||||
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
|
||||
/* is a DHCP client doing an ARP check? */
|
||||
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_STATE_CHECKING)) {
|
||||
if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
|
||||
ip4_addr_get_u32(addr)));
|
||||
/* did a host respond with the address we
|
||||
were offered by the DHCP server? */
|
||||
if (ip4_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
||||
if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) {
|
||||
/* we will not accept the offered address */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
|
||||
|
@ -899,7 +918,7 @@ dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
|
|||
static err_t
|
||||
dhcp_decline(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result = ERR_OK;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
|
||||
|
@ -908,14 +927,14 @@ dhcp_decline(struct netif *netif)
|
|||
result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
|
||||
if (result == ERR_OK) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
/* resize pbuf to reflect true size of options */
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* per section 4.4.4, broadcast DECLINE messages */
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||
} else {
|
||||
|
@ -941,7 +960,7 @@ dhcp_decline(struct netif *netif)
|
|||
static err_t
|
||||
dhcp_discover(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result = ERR_OK;
|
||||
u16_t msecs;
|
||||
u8_t i;
|
||||
|
@ -966,7 +985,7 @@ dhcp_discover(struct netif *netif)
|
|||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
||||
|
@ -1001,7 +1020,7 @@ dhcp_bind(struct netif *netif)
|
|||
struct dhcp *dhcp;
|
||||
ip4_addr_t sn_mask, gw_addr;
|
||||
LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
|
||||
dhcp = netif->dhcp;
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
|
||||
|
@ -1107,7 +1126,7 @@ dhcp_bind(struct netif *netif)
|
|||
err_t
|
||||
dhcp_renew(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
u8_t i;
|
||||
|
@ -1159,7 +1178,7 @@ dhcp_renew(struct netif *netif)
|
|||
static err_t
|
||||
dhcp_rebind(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
u8_t i;
|
||||
|
@ -1209,7 +1228,7 @@ dhcp_rebind(struct netif *netif)
|
|||
static err_t
|
||||
dhcp_reboot(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
u8_t i;
|
||||
|
@ -1220,10 +1239,10 @@ dhcp_reboot(struct netif *netif)
|
|||
result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
|
||||
if (result == ERR_OK) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
|
||||
|
@ -1253,14 +1272,14 @@ dhcp_reboot(struct netif *netif)
|
|||
|
||||
/**
|
||||
* @ingroup dhcp4
|
||||
* Release a DHCP lease.
|
||||
* Release a DHCP lease (usually called before @ref dhcp_stop).
|
||||
*
|
||||
* @param netif network interface which must release its lease
|
||||
*/
|
||||
err_t
|
||||
dhcp_release(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
err_t result;
|
||||
ip_addr_t server_ip_addr;
|
||||
u8_t is_dhcp_supplied_address;
|
||||
|
@ -1295,7 +1314,7 @@ dhcp_release(struct netif *netif)
|
|||
result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
|
||||
if (result == ERR_OK) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
|
||||
|
@ -1309,7 +1328,7 @@ dhcp_release(struct netif *netif)
|
|||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
|
||||
}
|
||||
/* remove IP address from interface (prevents routing from selecting this interface) */
|
||||
netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
|
||||
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1325,7 +1344,7 @@ dhcp_stop(struct netif *netif)
|
|||
{
|
||||
struct dhcp *dhcp;
|
||||
LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
|
||||
dhcp = netif->dhcp;
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
|
||||
/* netif is DHCP configured? */
|
||||
|
@ -1410,14 +1429,15 @@ dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif)
|
|||
if (netif->hostname != NULL) {
|
||||
size_t namelen = strlen(netif->hostname);
|
||||
if (namelen > 0) {
|
||||
u8_t len;
|
||||
size_t len;
|
||||
const char *p = netif->hostname;
|
||||
/* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME
|
||||
and 1 byte for trailer) */
|
||||
size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3;
|
||||
LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
|
||||
len = LWIP_MIN(namelen, available);
|
||||
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len);
|
||||
LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF);
|
||||
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len);
|
||||
while (len--) {
|
||||
dhcp_option_byte(dhcp, *p++);
|
||||
}
|
||||
|
@ -1487,7 +1507,7 @@ again:
|
|||
int decode_idx = -1;
|
||||
u16_t val_offset = offset + 2;
|
||||
/* len byte might be in the next pbuf */
|
||||
if (offset + 1 < q->len) {
|
||||
if ((offset + 1) < q->len) {
|
||||
len = options[offset + 1];
|
||||
} else {
|
||||
len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
|
||||
|
@ -1511,14 +1531,16 @@ again:
|
|||
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
||||
decode_idx = DHCP_OPTION_IDX_ROUTER;
|
||||
break;
|
||||
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||
case(DHCP_OPTION_DNS_SERVER):
|
||||
/* special case: there might be more than one server */
|
||||
LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;);
|
||||
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
|
||||
/* limit number of DNS servers */
|
||||
decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
|
||||
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
||||
decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
|
||||
break;
|
||||
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||
case(DHCP_OPTION_LEASE_TIME):
|
||||
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
|
||||
decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
|
||||
|
@ -1526,7 +1548,7 @@ again:
|
|||
#if LWIP_DHCP_GET_NTP_SRV
|
||||
case(DHCP_OPTION_NTP):
|
||||
/* special case: there might be more than one server */
|
||||
LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;);
|
||||
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
|
||||
/* limit number of NTP servers */
|
||||
decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
|
||||
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
||||
|
@ -1568,18 +1590,20 @@ decode_next:
|
|||
LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
|
||||
if (!dhcp_option_given(dhcp, decode_idx)) {
|
||||
copy_len = LWIP_MIN(decode_len, 4);
|
||||
pbuf_copy_partial(q, &value, copy_len, val_offset);
|
||||
if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
if (decode_len > 4) {
|
||||
/* decode more than one u32_t */
|
||||
LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
|
||||
LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
|
||||
dhcp_got_option(dhcp, decode_idx);
|
||||
dhcp_set_option_value(dhcp, decode_idx, htonl(value));
|
||||
dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
|
||||
decode_len -= 4;
|
||||
val_offset += 4;
|
||||
decode_idx++;
|
||||
goto decode_next;
|
||||
} else if (decode_len == 4) {
|
||||
value = ntohl(value);
|
||||
value = lwip_ntohl(value);
|
||||
} else {
|
||||
LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
|
||||
value = ((u8_t*)&value)[0];
|
||||
|
@ -1624,7 +1648,9 @@ decode_next:
|
|||
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
|
||||
(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
|
||||
/* copy bootp file name, don't care for sname (server hostname) */
|
||||
pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS);
|
||||
if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
/* make sure the string is really NULL-terminated */
|
||||
dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
|
||||
}
|
||||
|
@ -1652,11 +1678,11 @@ static void
|
|||
dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct netif *netif = ip_current_input_netif();
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
|
||||
u8_t msg_type;
|
||||
u8_t i;
|
||||
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
/* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */
|
||||
|
@ -1665,7 +1691,7 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
}
|
||||
|
||||
LWIP_ASSERT("invalid server address type", IP_IS_V4(addr));
|
||||
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
|
||||
ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
|
||||
|
@ -1696,9 +1722,9 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
}
|
||||
}
|
||||
/* match transaction ID against what we expected */
|
||||
if (ntohl(reply_msg->xid) != dhcp->xid) {
|
||||
if (lwip_ntohl(reply_msg->xid) != dhcp->xid) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
|
||||
("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
/* option fields could be unfold? */
|
||||
|
@ -1827,7 +1853,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||
dhcp->msg_out->htype = DHCP_HTYPE_ETH;
|
||||
dhcp->msg_out->hlen = netif->hwaddr_len;
|
||||
dhcp->msg_out->hops = 0;
|
||||
dhcp->msg_out->xid = htonl(dhcp->xid);
|
||||
dhcp->msg_out->xid = lwip_htonl(dhcp->xid);
|
||||
dhcp->msg_out->secs = 0;
|
||||
/* we don't need the broadcast flag since we can receive unicast traffic
|
||||
before being fully configured! */
|
||||
|
@ -1914,11 +1940,9 @@ dhcp_option_trailer(struct dhcp *dhcp)
|
|||
u8_t
|
||||
dhcp_supplied_address(const struct netif *netif)
|
||||
{
|
||||
if ((netif != NULL) && (netif->dhcp != NULL)) {
|
||||
if ((netif->dhcp->state == DHCP_STATE_BOUND) ||
|
||||
(netif->dhcp->state == DHCP_STATE_RENEWING)) {
|
||||
return 1;
|
||||
}
|
||||
if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
|
||||
struct dhcp* dhcp = netif_dhcp_data(netif);
|
||||
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "lwip/snmp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "netif/lwip_ethernet.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -71,8 +72,7 @@
|
|||
*/
|
||||
#define ARP_MAXPENDING 5
|
||||
|
||||
#define HWTYPE_ETHERNET 1
|
||||
|
||||
/** ARP states */
|
||||
enum etharp_state {
|
||||
ETHARP_STATE_EMPTY = 0,
|
||||
ETHARP_STATE_PENDING,
|
||||
|
@ -240,7 +240,7 @@ etharp_tmr(void)
|
|||
* old entries. Heuristic choose the least important entry for recycling.
|
||||
*
|
||||
* @param ipaddr IP address to find in ARP cache, or to add if not found.
|
||||
* @param flags @see definition of ETHARP_FLAG_*
|
||||
* @param flags See @ref etharp_state
|
||||
* @param netif netif related to this address (used for NETIF_HWADDRHINT)
|
||||
*
|
||||
* @return The ARP entry index that matched or is created, ERR_MEM if no
|
||||
|
@ -394,47 +394,6 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif)
|
|||
return (err_t)i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an IP 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
|
||||
etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const struct eth_addr *dst)
|
||||
{
|
||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
struct eth_vlan_hdr *vlanhdr;
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
|
||||
(netif->hwaddr_len == ETH_HWADDR_LEN));
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_VLAN);
|
||||
vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR);
|
||||
vlanhdr->prio_vid = 0;
|
||||
vlanhdr->tpid = PP_HTONS(ETHTYPE_IP);
|
||||
if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) {
|
||||
/* packet shall not contain VLAN header, so hide it and set correct ethertype */
|
||||
pbuf_header(p, -SIZEOF_VLAN_HDR);
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_IP);
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
ETHADDR32_COPY(ðhdr->dest, dst);
|
||||
ETHADDR16_COPY(ðhdr->src, src);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
|
||||
/* send the packet */
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (or insert) a IP/MAC address pair in the ARP cache.
|
||||
*
|
||||
|
@ -444,7 +403,7 @@ etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const
|
|||
* @param netif netif related to this entry (used for NETIF_ADDRHINT)
|
||||
* @param ipaddr IP address of the inserted ARP entry.
|
||||
* @param ethaddr Ethernet address of the inserted ARP entry.
|
||||
* @param flags @see definition of ETHARP_FLAG_*
|
||||
* @param flags See @ref etharp_state
|
||||
*
|
||||
* @return
|
||||
* - ERR_OK Successfully updated ARP cache.
|
||||
|
@ -518,7 +477,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et
|
|||
arp_table[i].q = NULL;
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* send the queued IP packet */
|
||||
etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
|
||||
ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
@ -532,7 +491,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et
|
|||
*
|
||||
* @param ipaddr IP address for the new static entry
|
||||
* @param ethaddr ethernet address for the new static entry
|
||||
* @return @see return values of etharp_add_static_entry
|
||||
* @return See return values of etharp_add_static_entry
|
||||
*/
|
||||
err_t
|
||||
etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr)
|
||||
|
@ -658,56 +617,6 @@ etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_a
|
|||
}
|
||||
}
|
||||
|
||||
#if ETHARP_TRUST_IP_MAC
|
||||
/**
|
||||
* Updates the ARP table using the given IP packet.
|
||||
*
|
||||
* Uses the incoming IP packet's source address to update the
|
||||
* ARP cache for the local network. The function does not alter
|
||||
* or free the packet. This function must be called before the
|
||||
* packet p is passed to the IP layer.
|
||||
*
|
||||
* @param netif The lwIP network interface on which the IP packet pbuf arrived.
|
||||
* @param p The IP packet that arrived on netif.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
void
|
||||
etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
struct ip_hdr *iphdr;
|
||||
ip4_addr_t iphdr_src;
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
|
||||
/* Only insert an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
|
||||
ip4_addr_copy(iphdr_src, iphdr->src);
|
||||
|
||||
/* source is not on the local network? */
|
||||
if (!ip4_addr_netcmp(&iphdr_src, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {
|
||||
/* do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
|
||||
/* update the source IP address in the cache, if present */
|
||||
/* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
|
||||
* back soon (for example, if the destination IP address is ours. */
|
||||
etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
|
||||
}
|
||||
#endif /* ETHARP_TRUST_IP_MAC */
|
||||
|
||||
/**
|
||||
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
|
||||
* send out queued IP packets. Updates cache with snooped address pairs.
|
||||
|
@ -715,47 +624,22 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
|
|||
* Should be called for incoming ARP packets. The pbuf in the argument
|
||||
* is freed by this function.
|
||||
*
|
||||
* @param netif The lwIP network interface on which the ARP packet pbuf arrived.
|
||||
* @param ethaddr Ethernet address of netif.
|
||||
* @param p The ARP packet that arrived on netif. Is freed by this function.
|
||||
*
|
||||
* @return NULL
|
||||
* @param netif The lwIP network interface on which the ARP packet pbuf arrived.
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
void
|
||||
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
etharp_input(struct pbuf *p, struct netif *netif)
|
||||
{
|
||||
struct etharp_hdr *hdr;
|
||||
struct eth_hdr *ethhdr;
|
||||
/* these are aligned properly, whereas the ARP header fields might not be */
|
||||
ip4_addr_t sipaddr, dipaddr;
|
||||
u8_t for_us;
|
||||
#if LWIP_AUTOIP
|
||||
const u8_t * ethdst_hwaddr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
|
||||
/* drop short ARP packets: we have to check for p->len instead of p->tot_len here
|
||||
since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
|
||||
if (p->len < SIZEOF_ETHARP_PACKET) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
|
||||
(s16_t)SIZEOF_ETHARP_PACKET));
|
||||
ETHARP_STATS_INC(etharp.lenerr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||
hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
hdr = (struct etharp_hdr *)p->payload;
|
||||
|
||||
/* RFC 826 "Packet Reception": */
|
||||
if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
|
||||
|
@ -763,7 +647,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
(hdr->protolen != sizeof(ip4_addr_t)) ||
|
||||
(hdr->proto != PP_HTONS(ETHTYPE_IP))) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
||||
("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
||||
hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
|
@ -808,55 +692,54 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
* reply. In any case, we time-stamp any existing ARP entry,
|
||||
* and possibly send out an IP packet that was queued on it. */
|
||||
|
||||
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
|
||||
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
|
||||
/* ARP request for our address? */
|
||||
if (for_us) {
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n"));
|
||||
/* Re-use pbuf to send ARP reply.
|
||||
Since we are re-using an existing pbuf, we can't call etharp_raw since
|
||||
that would allocate a new pbuf. */
|
||||
hdr->opcode = htons(ARP_REPLY);
|
||||
hdr->opcode = lwip_htons(ARP_REPLY);
|
||||
|
||||
IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
|
||||
IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif));
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
|
||||
(netif->hwaddr_len == ETH_HWADDR_LEN));
|
||||
#if LWIP_AUTOIP
|
||||
/* If we are using Link-Local, all ARP packets that contain a Link-Local
|
||||
* 'sender IP address' MUST be sent using link-layer broadcast instead of
|
||||
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
|
||||
ethdst_hwaddr = ip4_addr_islinklocal(netif_ip4_addr(netif)) ? (const u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
|
||||
#if LWIP_AUTOIP
|
||||
ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr);
|
||||
#else /* LWIP_AUTOIP */
|
||||
ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
|
||||
ETHADDR16_COPY(ðhdr->src, ethaddr);
|
||||
|
||||
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
|
||||
are already correct, we tested that before */
|
||||
|
||||
ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
|
||||
ETHADDR16_COPY(&hdr->shwaddr, netif->hwaddr);
|
||||
|
||||
/* return ARP reply */
|
||||
netif->linkoutput(netif, p);
|
||||
#if LWIP_AUTOIP
|
||||
/* If we are using Link-Local, all ARP packets that contain a Link-Local
|
||||
* 'sender IP address' MUST be sent using link-layer broadcast instead of
|
||||
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
|
||||
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
|
||||
ethernet_output(netif, p, &hdr->shwaddr, ðbroadcast, ETHTYPE_ARP);
|
||||
} else
|
||||
#endif /* LWIP_AUTOIP */
|
||||
{
|
||||
ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP);
|
||||
}
|
||||
|
||||
/* we are not configured? */
|
||||
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
|
||||
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
|
||||
/* request was not directed to us */
|
||||
} else {
|
||||
/* { for_us == 0 and netif->ip_addr.addr != 0 } */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
|
||||
}
|
||||
break;
|
||||
case PP_HTONS(ARP_REPLY):
|
||||
/* ARP reply. We already updated the ARP cache earlier. */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
|
||||
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
|
||||
/* DHCP wants to know about ARP replies from any host with an
|
||||
* IP address also offered to us by the DHCP server. We do not
|
||||
|
@ -866,7 +749,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
|
||||
ETHARP_STATS_INC(etharp.err);
|
||||
break;
|
||||
}
|
||||
|
@ -899,8 +782,7 @@ etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
|
|||
}
|
||||
}
|
||||
|
||||
return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
|
||||
&arp_table[arp_idx].ethaddr);
|
||||
return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -919,7 +801,7 @@ etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
|
|||
*
|
||||
* @return
|
||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
||||
* or the return type of either etharp_query() or etharp_send_ip().
|
||||
* or the return type of either etharp_query() or ethernet_output().
|
||||
*/
|
||||
err_t
|
||||
etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
||||
|
@ -932,19 +814,6 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||
LWIP_ASSERT("q != NULL", q != NULL);
|
||||
LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
|
||||
|
||||
/* make room for Ethernet header - should not fail */
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr) + SIZEOF_VLAN_HDR) != 0) {
|
||||
#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
/* bail out */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("etharp_output: could not allocate room for header.\n"));
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
/* Determine on destination hardware address. Broadcasts and multicasts
|
||||
* are special, other IP addresses are looked up in the ARP table. */
|
||||
|
||||
|
@ -971,11 +840,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||
if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
|
||||
!ip4_addr_islinklocal(ipaddr)) {
|
||||
#if LWIP_AUTOIP
|
||||
struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
SIZEOF_VLAN_HDR +
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
sizeof(struct eth_hdr));
|
||||
struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload);
|
||||
/* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
|
||||
a link-local source address must always be "directly to its destination
|
||||
on the same physical link. The host MUST NOT send the packet to any
|
||||
|
@ -1009,6 +874,9 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||
if (etharp_cached_entry < ARP_TABLE_SIZE) {
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
|
||||
#if ETHARP_TABLE_MATCH_NETIF
|
||||
(arp_table[etharp_cached_entry].netif == netif) &&
|
||||
#endif
|
||||
(ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
|
||||
/* the per-pcb-cached entry is stable and the right one! */
|
||||
ETHARP_STATS_INC(etharp.cachehit);
|
||||
|
@ -1023,6 +891,9 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||
throughput and etharp_find_entry() is kind of slow */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; i++) {
|
||||
if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
|
||||
#if ETHARP_TABLE_MATCH_NETIF
|
||||
(arp_table[i].netif == netif) &&
|
||||
#endif
|
||||
(ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) {
|
||||
/* found an existing, stable entry */
|
||||
ETHARP_SET_HINT(netif, i);
|
||||
|
@ -1037,7 +908,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||
/* continuation for multicast/broadcast destinations */
|
||||
/* obtain source Ethernet address of the given interface */
|
||||
/* send packet directly on the link */
|
||||
return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
|
||||
return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1137,7 +1008,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
|
|||
/* we have a valid IP->Ethernet address mapping */
|
||||
ETHARP_SET_HINT(netif, i);
|
||||
/* send the packet */
|
||||
result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
|
||||
result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP);
|
||||
/* pending entry? (either just created or already pending */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* entry is still pending, queue the given packet 'q' */
|
||||
|
@ -1157,7 +1028,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
|
|||
}
|
||||
if (copy_needed) {
|
||||
/* copy the whole packet into new pbufs */
|
||||
p = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
||||
p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||
if (p != NULL) {
|
||||
if (pbuf_copy(p, q) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
|
@ -1245,10 +1116,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
|
|||
* ERR_MEM if the ARP packet couldn't be allocated
|
||||
* any other err_t on failure
|
||||
*/
|
||||
#if !LWIP_AUTOIP
|
||||
static
|
||||
#endif /* LWIP_AUTOIP */
|
||||
err_t
|
||||
static err_t
|
||||
etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
||||
const struct eth_addr *ethdst_addr,
|
||||
const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
|
||||
|
@ -1257,19 +1125,12 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|||
{
|
||||
struct pbuf *p;
|
||||
err_t result = ERR_OK;
|
||||
struct eth_hdr *ethhdr;
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
struct eth_vlan_hdr *vlanhdr;
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
struct etharp_hdr *hdr;
|
||||
#if LWIP_AUTOIP
|
||||
const u8_t * ethdst_hwaddr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
|
||||
/* allocate a pbuf for the outgoing ARP request packet */
|
||||
p = pbuf_alloc(PBUF_RAW_TX, SIZEOF_ETHARP_PACKET_TX, PBUF_RAM);
|
||||
p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM);
|
||||
/* could allocate a pbuf for an ARP request? */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
|
@ -1278,26 +1139,15 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
|
||||
(p->len >= SIZEOF_ETHARP_PACKET_TX));
|
||||
(p->len >= SIZEOF_ETHARP_HDR));
|
||||
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR);
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||
#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
hdr = (struct etharp_hdr *)p->payload;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
|
||||
hdr->opcode = htons(opcode);
|
||||
hdr->opcode = lwip_htons(opcode);
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
|
||||
(netif->hwaddr_len == ETH_HWADDR_LEN));
|
||||
#if LWIP_AUTOIP
|
||||
/* If we are using Link-Local, all ARP packets that contain a Link-Local
|
||||
* 'sender IP address' MUST be sent using link-layer broadcast instead of
|
||||
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
|
||||
ethdst_hwaddr = ip4_addr_islinklocal(ipsrc_addr) ? (const u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
/* Write the ARP MAC-Addresses */
|
||||
ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
|
||||
ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
|
||||
|
@ -1312,30 +1162,19 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|||
hdr->hwlen = ETH_HWADDR_LEN;
|
||||
hdr->protolen = sizeof(ip4_addr_t);
|
||||
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_VLAN);
|
||||
vlanhdr->tpid = PP_HTONS(ETHTYPE_ARP);
|
||||
vlanhdr->prio_vid = 0;
|
||||
if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) {
|
||||
/* packet shall not contain VLAN header, so hide it and set correct ethertype */
|
||||
pbuf_header(p, -SIZEOF_VLAN_HDR);
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_ARP);
|
||||
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
|
||||
|
||||
/* Write the Ethernet MAC-Addresses */
|
||||
#if LWIP_AUTOIP
|
||||
ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr);
|
||||
#else /* LWIP_AUTOIP */
|
||||
ETHADDR16_COPY(ðhdr->dest, ethdst_addr);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
ETHADDR16_COPY(ðhdr->src, ethsrc_addr);
|
||||
|
||||
/* send ARP query */
|
||||
result = netif->linkoutput(netif, p);
|
||||
#if LWIP_AUTOIP
|
||||
/* If we are using Link-Local, all ARP packets that contain a Link-Local
|
||||
* 'sender IP address' MUST be sent using link-layer broadcast instead of
|
||||
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
|
||||
if(ip4_addr_islinklocal(ipsrc_addr)) {
|
||||
ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP);
|
||||
} else
|
||||
#endif /* LWIP_AUTOIP */
|
||||
{
|
||||
ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP);
|
||||
}
|
||||
|
||||
ETHARP_STATS_INC(etharp.xmit);
|
||||
/* free ARP query packet */
|
||||
pbuf_free(p);
|
||||
|
|
|
@ -81,7 +81,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
#endif /* LWIP_DEBUG */
|
||||
struct icmp_echo_hdr *iecho;
|
||||
const struct ip_hdr *iphdr_in;
|
||||
s16_t hlen;
|
||||
u16_t hlen;
|
||||
const ip4_addr_t* src;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
|
@ -148,7 +148,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
#endif
|
||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
if (pbuf_header(p, (hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
||||
if (pbuf_header(p, (s16_t)(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
|
||||
*/
|
||||
|
@ -167,7 +167,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
/* copy the ip header */
|
||||
MEMCPY(r->payload, iphdr_in, hlen);
|
||||
/* switch r->payload back to icmp header (cannot fail) */
|
||||
if (pbuf_header(r, -hlen)) {
|
||||
if (pbuf_header(r, (s16_t)-hlen)) {
|
||||
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
||||
pbuf_free(r);
|
||||
goto icmperr;
|
||||
|
@ -194,7 +194,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
/* 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)) {
|
||||
if (pbuf_header(p, (s16_t)hlen)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
|
||||
} else {
|
||||
err_t ret;
|
||||
|
@ -236,7 +236,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
MIB2_STATS_INC(mib2.icmpoutechoreps);
|
||||
|
||||
/* send an ICMP packet */
|
||||
ret = ip4_output_if(p, src, IP_HDRINCL,
|
||||
ret = ip4_output_if(p, src, LWIP_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)));
|
||||
|
@ -247,7 +247,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
if (type == ICMP_DUR) {
|
||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
||||
} else if (type == ICMP_TE) {
|
||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
||||
MIB2_STATS_INC(mib2.icmpintimeexcds);
|
||||
} else if (type == ICMP_PP) {
|
||||
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
||||
} else if (type == ICMP_SQ) {
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* @file
|
||||
* IGMP - Internet Group Management Protocol
|
||||
*
|
||||
* @defgroup igmp IGMP
|
||||
* @ingroup ip4
|
||||
* To be called from TCPIP thread
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -38,12 +41,6 @@
|
|||
* source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup igmp IGMP
|
||||
* @ingroup ip4
|
||||
* To be called from TCPIP thread
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
Note 1)
|
||||
Although the rfc requires V1 AND V2 capability
|
||||
|
@ -95,63 +92,21 @@ Steve Reynolds
|
|||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/igmp.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 err_t igmp_remove_group(struct netif* netif, struct igmp_group *group);
|
||||
static void igmp_timeout(struct netif *netif, 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 void igmp_send(struct netif *netif, 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
|
||||
*/
|
||||
|
@ -187,7 +142,7 @@ igmp_start(struct netif *netif)
|
|||
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);
|
||||
netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
|
@ -204,36 +159,24 @@ igmp_start(struct netif *netif)
|
|||
err_t
|
||||
igmp_stop(struct netif *netif)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
struct igmp_group *prev = NULL;
|
||||
struct igmp_group *next;
|
||||
struct igmp_group *group = netif_igmp_data(netif);
|
||||
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL);
|
||||
|
||||
/* 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;
|
||||
struct igmp_group *next = group->next; /* avoid use-after-free below */
|
||||
|
||||
/* 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), NETIF_DEL_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* free group */
|
||||
memp_free(MEMP_IGMP_GROUP, group);
|
||||
|
||||
/* move to "next" */
|
||||
group = next;
|
||||
}
|
||||
|
@ -248,14 +191,17 @@ igmp_stop(struct netif *netif)
|
|||
void
|
||||
igmp_report_groups(struct netif *netif)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
struct igmp_group *group = netif_igmp_data(netif);
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif));
|
||||
|
||||
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
|
||||
if(group != NULL) {
|
||||
group = group->next;
|
||||
}
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->netif == netif) && (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
|
||||
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
}
|
||||
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
@ -271,10 +217,10 @@ igmp_report_groups(struct netif *netif)
|
|||
struct igmp_group *
|
||||
igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
struct igmp_group *group = netif_igmp_data(ifp);
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->netif == ifp) && (ip4_addr_cmp(&(group->group_address), addr))) {
|
||||
if (ip4_addr_cmp(&(group->group_address), addr)) {
|
||||
return group;
|
||||
}
|
||||
group = group->next;
|
||||
|
@ -298,6 +244,7 @@ struct igmp_group *
|
|||
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
||||
{
|
||||
struct igmp_group *group;
|
||||
struct igmp_group *list_head = netif_igmp_data(ifp);
|
||||
|
||||
/* Search if the group already exists */
|
||||
group = igmp_lookfor_group(ifp, addr);
|
||||
|
@ -305,19 +252,30 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
|||
/* 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;
|
||||
/* Ensure allsystems group is always first in list */
|
||||
if (list_head == NULL) {
|
||||
/* this is the first entry in linked list */
|
||||
LWIP_ASSERT("igmp_lookup_group: first group must be allsystems",
|
||||
(ip4_addr_cmp(addr, &allsystems) != 0));
|
||||
group->next = NULL;
|
||||
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
|
||||
} else {
|
||||
/* append _after_ first entry */
|
||||
LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems",
|
||||
(ip4_addr_cmp(addr, &allsystems) == 0));
|
||||
group->next = list_head->next;
|
||||
list_head->next = group;
|
||||
}
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
|
||||
|
@ -328,35 +286,28 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove a group in the global igmp_group_list
|
||||
* Remove a group in the global igmp_group_list, but don't free it yet
|
||||
*
|
||||
* @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)
|
||||
igmp_remove_group(struct netif* netif, struct igmp_group *group)
|
||||
{
|
||||
err_t err = ERR_OK;
|
||||
struct igmp_group *tmp_group;
|
||||
|
||||
/* 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;
|
||||
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
|
||||
for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) {
|
||||
if (tmp_group->next == group) {
|
||||
tmp_group->next = group->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* free group */
|
||||
memp_free(MEMP_IGMP_GROUP, group);
|
||||
/* Group not found in the global igmp_group_list */
|
||||
if (tmp_group == NULL) {
|
||||
err = ERR_ARG;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -427,12 +378,16 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
|
|||
IGMP_STATS_INC(igmp.rx_general);
|
||||
}
|
||||
|
||||
groupref = igmp_group_list;
|
||||
groupref = netif_igmp_data(inp);
|
||||
|
||||
/* Do not send messages on the all systems group address! */
|
||||
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
|
||||
if(groupref != NULL) {
|
||||
groupref = groupref->next;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
igmp_delaying_member(groupref, igmp->igmp_maxresp);
|
||||
groupref = groupref->next;
|
||||
}
|
||||
} else {
|
||||
|
@ -473,7 +428,7 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
|
|||
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->igmp_msgtype, group->group_state, (void*)&group, (void*)inp));
|
||||
IGMP_STATS_INC(igmp.proterr);
|
||||
break;
|
||||
}
|
||||
|
@ -557,11 +512,11 @@ igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|||
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);
|
||||
netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
IGMP_STATS_INC(igmp.tx_join);
|
||||
igmp_send(group, IGMP_V2_MEMB_REPORT);
|
||||
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
|
||||
|
||||
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
|
||||
|
@ -645,11 +600,14 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|||
|
||||
/* If there is no other use of the group */
|
||||
if (group->use <= 1) {
|
||||
/* Remove the group from the list */
|
||||
igmp_remove_group(netif, group);
|
||||
|
||||
/* 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);
|
||||
igmp_send(netif, group, IGMP_LEAVE_GROUP);
|
||||
}
|
||||
|
||||
/* Disable the group at the MAC level */
|
||||
|
@ -657,15 +615,11 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|||
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);
|
||||
netif->igmp_mac_filter(netif, groupaddr, NETIF_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);
|
||||
/* Free group struct */
|
||||
memp_free(MEMP_IGMP_GROUP, group);
|
||||
} else {
|
||||
/* Decrement group use */
|
||||
group->use--;
|
||||
|
@ -684,16 +638,21 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
|||
void
|
||||
igmp_tmr(void)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
struct netif *netif = netif_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->timer > 0) {
|
||||
group->timer--;
|
||||
if (group->timer == 0) {
|
||||
igmp_timeout(group);
|
||||
while (netif != NULL) {
|
||||
struct igmp_group *group = netif_igmp_data(netif);
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->timer > 0) {
|
||||
group->timer--;
|
||||
if (group->timer == 0) {
|
||||
igmp_timeout(netif, group);
|
||||
}
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
group = group->next;
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,7 +663,7 @@ igmp_tmr(void)
|
|||
* @param group an igmp_group for which a timeout is reached
|
||||
*/
|
||||
static void
|
||||
igmp_timeout(struct igmp_group *group)
|
||||
igmp_timeout(struct netif *netif, 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) */
|
||||
|
@ -712,10 +671,12 @@ igmp_timeout(struct igmp_group *group)
|
|||
(!(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));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif));
|
||||
|
||||
group->group_state = IGMP_GROUP_IDLE_MEMBER;
|
||||
|
||||
IGMP_STATS_INC(igmp.tx_report);
|
||||
igmp_send(group, IGMP_V2_MEMB_REPORT);
|
||||
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,13 +726,11 @@ igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
|
|||
* 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
|
||||
protocol header; if dest == LWIP_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 == IP4_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
|
||||
|
@ -795,11 +754,11 @@ igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|||
* @param type the type of igmp packet to send
|
||||
*/
|
||||
static void
|
||||
igmp_send(struct igmp_group *group, u8_t type)
|
||||
igmp_send(struct netif *netif, 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 src = *IP4_ADDR_ANY4;
|
||||
ip4_addr_t* dest = NULL;
|
||||
|
||||
/* IP header + "router alert" option + IGMP header */
|
||||
|
@ -809,7 +768,7 @@ igmp_send(struct igmp_group *group, u8_t type)
|
|||
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));
|
||||
ip4_addr_copy(src, *netif_ip4_addr(netif));
|
||||
|
||||
if (type == IGMP_V2_MEMB_REPORT) {
|
||||
dest = &(group->group_address);
|
||||
|
@ -828,7 +787,7 @@ igmp_send(struct igmp_group *group, u8_t type)
|
|||
igmp->igmp_checksum = 0;
|
||||
igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
|
||||
|
||||
igmp_ip_output_if(p, &src, dest, group->netif);
|
||||
igmp_ip_output_if(p, &src, dest, netif);
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/dhcp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -106,7 +106,9 @@ static u16_t ip_id;
|
|||
/** The default netif used for multicast */
|
||||
static struct netif* ip4_default_multicast_netif;
|
||||
|
||||
/** Set a default netif for IPv4 multicast. */
|
||||
/**
|
||||
* @ingroup ip4
|
||||
* Set a default netif for IPv4 multicast. */
|
||||
void
|
||||
ip4_set_default_multicast_netif(struct netif* default_multicast_netif)
|
||||
{
|
||||
|
@ -175,7 +177,7 @@ ip4_route(const ip4_addr_t *dest)
|
|||
/* loopif is disabled, looopback traffic is passed through any netif */
|
||||
if (ip4_addr_isloopback(dest)) {
|
||||
/* don't check for link on loopback traffic */
|
||||
if (netif_is_up(netif_default)) {
|
||||
if (netif_default != NULL && netif_is_up(netif_default)) {
|
||||
return netif_default;
|
||||
}
|
||||
/* default netif is not up, just use any netif for loopback traffic */
|
||||
|
@ -220,13 +222,12 @@ ip4_route(const ip4_addr_t *dest)
|
|||
* that may not be forwarded, or whether datagrams to that destination
|
||||
* may be forwarded.
|
||||
* @param p the packet to forward
|
||||
* @param dest the destination IP address
|
||||
* @return 1: can forward 0: discard
|
||||
*/
|
||||
static int
|
||||
ip4_canforward(struct pbuf *p)
|
||||
{
|
||||
u32_t addr = htonl(ip4_addr_get_u32(ip4_current_dest_addr()));
|
||||
u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr()));
|
||||
|
||||
if (p->flags & PBUF_FLAG_LLBCAST) {
|
||||
/* don't route link-layer broadcasts */
|
||||
|
@ -265,6 +266,7 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||
struct netif *netif;
|
||||
|
||||
PERF_START;
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
if (!ip4_canforward(p)) {
|
||||
goto return_noroute;
|
||||
|
@ -402,7 +404,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
/* calculate IP header length in bytes */
|
||||
iphdr_hlen *= 4;
|
||||
/* obtain ip length in bytes */
|
||||
iphdr_len = ntohs(IPH_LEN(iphdr));
|
||||
iphdr_len = lwip_ntohs(IPH_LEN(iphdr));
|
||||
|
||||
/* Trim pbuf. This is especially required for packets < 60 bytes. */
|
||||
if (iphdr_len < p->tot_len) {
|
||||
|
@ -507,8 +509,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist after changing
|
||||
the netif's address (RFC3927 ch. 1.9) */
|
||||
if ((netif->autoip != NULL) &&
|
||||
ip4_addr_cmp(ip4_current_dest_addr(), &(netif->autoip->llipaddr))) {
|
||||
if (autoip_accept_packet(netif, ip4_current_dest_addr())) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
|
@ -517,6 +518,15 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
#endif /* LWIP_AUTOIP */
|
||||
}
|
||||
if (first) {
|
||||
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
|
||||
/* Packets sent to the loopback address must not be accepted on an
|
||||
* interface that does not have the loopback address assigned to it,
|
||||
* unless a non-loopback interface is used for loopback traffic. */
|
||||
if (ip4_addr_isloopback(ip4_current_dest_addr())) {
|
||||
netif = NULL;
|
||||
break;
|
||||
}
|
||||
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
|
||||
first = 0;
|
||||
netif = netif_list;
|
||||
} else {
|
||||
|
@ -543,7 +553,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||
ntohs(udphdr->dest)));
|
||||
lwip_ntohs(udphdr->dest)));
|
||||
if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n"));
|
||||
netif = inp;
|
||||
|
@ -588,6 +598,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
} else
|
||||
#endif /* IP_FORWARD */
|
||||
{
|
||||
IP_STATS_INC(ip.drop);
|
||||
MIB2_STATS_INC(mib2.ipinaddrerrors);
|
||||
MIB2_STATS_INC(mib2.ipindiscards);
|
||||
}
|
||||
|
@ -598,7 +609,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
|
||||
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n",
|
||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)));
|
||||
lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)));
|
||||
/* reassemble the packet*/
|
||||
p = ip4_reass(p);
|
||||
/* packet not fully reassembled yet? */
|
||||
|
@ -609,7 +620,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
lwip_ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
/* unsupported protocol feature */
|
||||
|
@ -716,13 +727,13 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||
* the IP header and calculates the IP header checksum. If the source
|
||||
* IP address is NULL, the IP address of the outgoing network
|
||||
* interface is filled in as source address.
|
||||
* If the destination IP address is IP_HDRINCL, p is assumed to already
|
||||
* If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already
|
||||
* include an IP header and p->payload points to it instead of the data.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an IP
|
||||
header and p->payload points to that IP header)
|
||||
* @param src the source IP address to send from (if src == IP_ADDR_ANY, the
|
||||
protocol header; if dest == LWIP_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 == IP4_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
|
||||
|
@ -758,7 +769,7 @@ ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|||
{
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
const ip4_addr_t *src_used = src;
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
if (ip4_addr_isany(src)) {
|
||||
src_used = netif_ip4_addr(netif);
|
||||
}
|
||||
|
@ -806,7 +817,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||
MIB2_STATS_INC(mib2.ipoutrequests);
|
||||
|
||||
/* Should the IP header be generated or is it already included in p? */
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
u16_t ip_hlen = IP_HLEN;
|
||||
#if IP_OPTIONS_SEND
|
||||
u16_t optlen_aligned = 0;
|
||||
|
@ -852,7 +863,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||
IPH_TTL_SET(iphdr, ttl);
|
||||
IPH_PROTO_SET(iphdr, proto);
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += LWIP_MAKE_U16(proto, ttl);
|
||||
chk_sum += PP_NTOHS(proto | (ttl << 8));
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
|
||||
/* dest cannot be NULL here */
|
||||
|
@ -865,21 +876,21 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||
IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
|
||||
IPH_TOS_SET(iphdr, tos);
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
|
||||
chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8));
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += iphdr->_len;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
IPH_ID_SET(iphdr, lwip_htons(ip_id));
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += iphdr->_id;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
++ip_id;
|
||||
|
||||
if (src == NULL) {
|
||||
ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY);
|
||||
ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4);
|
||||
} else {
|
||||
/* src cannot be NULL here */
|
||||
ip4_addr_copy(iphdr->src, *src);
|
||||
|
@ -951,9 +962,9 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||
* interface and calls upon ip_output_if to do the actual work.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an IP
|
||||
header and p->payload points to that IP header)
|
||||
* @param src the source IP address to send from (if src == IP_ADDR_ANY, the
|
||||
protocol header; if dest == LWIP_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 == IP4_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
|
||||
|
@ -986,9 +997,9 @@ ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
|||
* before calling ip_output_if.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an IP
|
||||
header and p->payload points to that IP header)
|
||||
* @param src the source IP address to send from (if src == IP_ADDR_ANY, the
|
||||
protocol header; if dest == LWIP_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 == IP4_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
|
||||
|
@ -1039,19 +1050,19 @@ ip4_debug_print(struct pbuf *p)
|
|||
(u16_t)IPH_V(iphdr),
|
||||
(u16_t)IPH_HL(iphdr),
|
||||
(u16_t)IPH_TOS(iphdr),
|
||||
ntohs(IPH_LEN(iphdr))));
|
||||
lwip_ntohs(IPH_LEN(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
|
||||
ntohs(IPH_ID(iphdr)),
|
||||
(u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 15 & 1),
|
||||
(u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 14 & 1),
|
||||
(u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 13 & 1),
|
||||
(u16_t)(ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)));
|
||||
lwip_ntohs(IPH_ID(iphdr)),
|
||||
(u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1),
|
||||
(u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1),
|
||||
(u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1),
|
||||
(u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
|
||||
(u16_t)IPH_TTL(iphdr),
|
||||
(u16_t)IPH_PROTO(iphdr),
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
lwip_ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||
ip4_addr1_16(&iphdr->src),
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
||||
/* used by IP4_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);
|
||||
|
||||
|
@ -183,10 +183,10 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
|||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
val = (val * base) + (u32_t)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else {
|
||||
break;
|
||||
|
@ -260,7 +260,7 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
|||
break;
|
||||
}
|
||||
if (addr) {
|
||||
ip4_addr_set_u32(addr, htonl(val));
|
||||
ip4_addr_set_u32(addr, lwip_htonl(val));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
|
|||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
inv[i++] = (char)('0' + rem);
|
||||
} while (*ap);
|
||||
while (i--) {
|
||||
if (len++ >= buflen) {
|
||||
|
|
|
@ -160,7 +160,7 @@ static int
|
|||
ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
||||
{
|
||||
u16_t pbufs_freed = 0;
|
||||
u8_t clen;
|
||||
u16_t clen;
|
||||
struct pbuf *p;
|
||||
struct ip_reass_helper *iprh;
|
||||
|
||||
|
@ -331,7 +331,7 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
|||
* 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 ipr points to the reassembly state
|
||||
* @param new_p points to the pbuf for the current fragment
|
||||
* @return 0 if invalid, >0 otherwise
|
||||
*/
|
||||
|
@ -340,14 +340,14 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||
{
|
||||
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
||||
struct pbuf *q;
|
||||
u16_t offset,len;
|
||||
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;
|
||||
len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
offset = (lwip_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. */
|
||||
|
@ -487,8 +487,7 @@ ip4_reass(struct pbuf *p)
|
|||
struct ip_hdr *fraghdr;
|
||||
struct ip_reassdata *ipr;
|
||||
struct ip_reass_helper *iprh;
|
||||
u16_t offset, len;
|
||||
u8_t clen;
|
||||
u16_t offset, len, clen;
|
||||
|
||||
IPFRAG_STATS_INC(ip_frag.recv);
|
||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
||||
|
@ -501,8 +500,8 @@ ip4_reass(struct pbuf *p)
|
|||
goto nullreturn;
|
||||
}
|
||||
|
||||
offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
|
||||
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
|
||||
len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
|
||||
/* Check if we are allowed to enqueue more datagrams. */
|
||||
clen = pbuf_clen(p);
|
||||
|
@ -530,7 +529,7 @@ ip4_reass(struct pbuf *p)
|
|||
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))));
|
||||
lwip_ntohs(IPH_ID(fraghdr))));
|
||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
||||
break;
|
||||
}
|
||||
|
@ -544,8 +543,8 @@ ip4_reass(struct pbuf *p)
|
|||
goto nullreturn;
|
||||
}
|
||||
} else {
|
||||
if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
|
||||
((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) {
|
||||
if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
|
||||
((lwip_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
|
||||
|
@ -582,7 +581,7 @@ ip4_reass(struct pbuf *p)
|
|||
/* 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_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len));
|
||||
IPH_OFFSET_SET(fraghdr, 0);
|
||||
IPH_CHKSUM_SET(fraghdr, 0);
|
||||
/* @todo: do we need to set/calculate the correct checksum? */
|
||||
|
@ -639,10 +638,6 @@ nullreturn:
|
|||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if IP_FRAG
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
static LWIP_DECLARE_MEMORY_ALIGNED(buf, IP_FRAG_MAX_MTU);
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
/** Allocate a new struct pbuf_custom_ref */
|
||||
static struct pbuf_custom_ref*
|
||||
|
@ -673,14 +668,12 @@ ipfrag_free_pbuf_custom(struct pbuf *p)
|
|||
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).
|
||||
* by pointing PBUF_REFs into p.
|
||||
*
|
||||
* @param p ip packet to send
|
||||
* @param netif the netif on which to send
|
||||
|
@ -692,81 +685,43 @@ 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
|
||||
struct ip_hdr *original_iphdr;
|
||||
struct ip_hdr *iphdr;
|
||||
const u16_t nfb = (netif->mtu - IP_HLEN) / 8;
|
||||
u16_t left, fragsize;
|
||||
u16_t ofo;
|
||||
int last;
|
||||
u16_t poff = IP_HLEN;
|
||||
u16_t tmp;
|
||||
|
||||
/* 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 */
|
||||
LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL);
|
||||
|
||||
/* Save original offset */
|
||||
tmp = ntohs(IPH_OFFSET(iphdr));
|
||||
tmp = lwip_ntohs(IPH_OFFSET(iphdr));
|
||||
ofo = tmp & IP_OFFMASK;
|
||||
omf = tmp & IP_MF;
|
||||
LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL);
|
||||
|
||||
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;
|
||||
fragsize = LWIP_MIN(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);
|
||||
rambuf = pbuf_alloc(PBUF_IP, fragsize, 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);
|
||||
poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff);
|
||||
/* make room for the IP header */
|
||||
if (pbuf_header(rambuf, IP_HLEN)) {
|
||||
pbuf_free(rambuf);
|
||||
|
@ -790,16 +745,14 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||
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;
|
||||
left_to_copy = fragsize;
|
||||
while (left_to_copy) {
|
||||
struct pbuf_custom_ref *pcr;
|
||||
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
|
||||
u16_t plen = p->len - poff;
|
||||
newpbuflen = LWIP_MIN(left_to_copy, plen);
|
||||
/* Is this pbuf already empty? */
|
||||
if (!newpbuflen) {
|
||||
poff = 0;
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
|
@ -809,7 +762,8 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||
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);
|
||||
newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc,
|
||||
(u8_t*)p->payload + poff, newpbuflen);
|
||||
if (newpbuf == NULL) {
|
||||
ip_frag_free_pbuf_custom_ref(pcr);
|
||||
pbuf_free(rambuf);
|
||||
|
@ -825,16 +779,23 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||
pbuf_cat(rambuf, newpbuf);
|
||||
left_to_copy -= newpbuflen;
|
||||
if (left_to_copy) {
|
||||
poff = 0;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
poff = newpbuflen;
|
||||
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));
|
||||
last = (left <= netif->mtu - IP_HLEN);
|
||||
|
||||
/* Set new offset and MF flag */
|
||||
tmp = (IP_OFFMASK & (ofo));
|
||||
if (!last) {
|
||||
tmp = tmp | IP_MF;
|
||||
}
|
||||
IPH_OFFSET_SET(iphdr, lwip_htons(tmp));
|
||||
IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN));
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
|
||||
|
@ -842,29 +803,6 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||
}
|
||||
#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.
|
||||
*/
|
||||
|
@ -879,13 +817,9 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||
*/
|
||||
|
||||
pbuf_free(rambuf);
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
left -= cop;
|
||||
left -= fragsize;
|
||||
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:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
IPv6 support in lwIP is very experimental.
|
|
@ -51,42 +51,20 @@
|
|||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/prot/lwip_ethernet.h"
|
||||
#include "netif/lwip_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, ...
|
||||
* For unicast addresses, ask the ND6 module what to do. It will either let us
|
||||
* send the the packet right away, or queue the packet for later itself, unless
|
||||
* an error occurs.
|
||||
*
|
||||
* @todo anycast addresses
|
||||
*
|
||||
|
@ -95,22 +73,14 @@ ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct et
|
|||
* @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_OK or the return value of @ref nd6_get_next_hop_addr_or_queue.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
const u8_t *hwaddr;
|
||||
err_t result;
|
||||
|
||||
/* multicast destination IP address? */
|
||||
if (ip6_addr_ismulticast(ip6addr)) {
|
||||
|
@ -123,37 +93,26 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
|||
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
||||
|
||||
/* Send out. */
|
||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
||||
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Ask ND6 what to do with the packet. */
|
||||
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
|
||||
if (result != ERR_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* If no hardware address is returned, nd6 has queued the packet for later. */
|
||||
if (hwaddr == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* We should queue packet on this interface. */
|
||||
pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR);
|
||||
return nd6_queue_packet(i, q);
|
||||
/* Send out the packet using the returned hardware address. */
|
||||
SMEMCPY(dest.addr, hwaddr, 6);
|
||||
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/prot/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
@ -80,8 +81,8 @@ void
|
|||
icmp6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct icmp6_hdr *icmp6hdr;
|
||||
struct pbuf * r;
|
||||
const ip6_addr_t * reply_src;
|
||||
struct pbuf *r;
|
||||
const ip6_addr_t *reply_src;
|
||||
|
||||
ICMP6_STATS_INC(icmp6.recv);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_frag.h"
|
||||
|
@ -93,7 +94,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
if (ip6_addr_islinklocal(dest)) {
|
||||
if (ip6_addr_isany(src)) {
|
||||
/* Use default netif, if Up. */
|
||||
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
|
||||
if (netif_default == NULL || !netif_is_up(netif_default) ||
|
||||
!netif_is_link_up(netif_default)) {
|
||||
return NULL;
|
||||
}
|
||||
return netif_default;
|
||||
|
@ -113,7 +115,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
}
|
||||
|
||||
/* netif not found, use default netif, if up */
|
||||
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
|
||||
if (netif_default == NULL || !netif_is_up(netif_default) ||
|
||||
!netif_is_link_up(netif_default)) {
|
||||
return NULL;
|
||||
}
|
||||
return netif_default;
|
||||
|
@ -141,15 +144,9 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
}
|
||||
|
||||
/* Get the netif for a suitable router. */
|
||||
i = nd6_select_router(dest, NULL);
|
||||
if (i >= 0) {
|
||||
if (default_router_list[i].neighbor_entry != NULL) {
|
||||
if (default_router_list[i].neighbor_entry->netif != NULL) {
|
||||
if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
|
||||
return default_router_list[i].neighbor_entry->netif;
|
||||
}
|
||||
}
|
||||
}
|
||||
netif = nd6_find_route(dest);
|
||||
if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) {
|
||||
return netif;
|
||||
}
|
||||
|
||||
/* try with the netif that matches the source address. */
|
||||
|
@ -171,7 +168,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
/* loopif is disabled, loopback traffic is passed through any netif */
|
||||
if (ip6_addr_isloopback(dest)) {
|
||||
/* don't check for link on loopback traffic */
|
||||
if (netif_is_up(netif_default)) {
|
||||
if (netif_default != NULL && netif_is_up(netif_default)) {
|
||||
return netif_default;
|
||||
}
|
||||
/* default netif is not up, just use any netif for loopback traffic */
|
||||
|
@ -192,6 +189,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup ip6
|
||||
* Select the best IPv6 source address for a given destination
|
||||
* IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
|
||||
* is assumed.
|
||||
|
@ -202,7 +200,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||
* source address is found
|
||||
*/
|
||||
const ip_addr_t *
|
||||
ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest)
|
||||
ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
|
||||
{
|
||||
const ip_addr_t *src = NULL;
|
||||
u8_t i;
|
||||
|
@ -288,8 +286,9 @@ ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
|
|||
{
|
||||
struct netif *netif;
|
||||
|
||||
/* do not forward link-local addresses */
|
||||
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
|
||||
/* do not forward link-local or loopback addresses */
|
||||
if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
|
||||
ip6_addr_isloopback(ip6_current_dest_addr())) {
|
||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
|
||||
IP6_STATS_INC(ip6.rterr);
|
||||
IP6_STATS_INC(ip6.drop);
|
||||
|
@ -451,7 +450,7 @@ ip6_input(struct pbuf *p, struct netif *inp)
|
|||
IP6_STATS_INC(ip6.drop);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* current header pointer. */
|
||||
ip_data.current_ip6_header = ip6hdr;
|
||||
|
||||
|
@ -507,12 +506,21 @@ ip6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
|
||||
/* Do not match link-local addresses to other netifs. */
|
||||
netif = NULL;
|
||||
break;
|
||||
}
|
||||
if (first) {
|
||||
if (ip6_addr_islinklocal(ip6_current_dest_addr())
|
||||
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
|
||||
|| ip6_addr_isloopback(ip6_current_dest_addr())
|
||||
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
|
||||
) {
|
||||
/* Do not match link-local addresses to other netifs. The loopback
|
||||
* address is to be considered link-local and packets to it should be
|
||||
* dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This
|
||||
* requirement cannot be implemented in the case that loopback
|
||||
* traffic is sent across a non-loopback interface, however.
|
||||
*/
|
||||
netif = NULL;
|
||||
break;
|
||||
}
|
||||
first = 0;
|
||||
netif = netif_list;
|
||||
} else {
|
||||
|
@ -641,7 +649,7 @@ netif_found:
|
|||
|
||||
case IP6_NEXTH_FRAGMENT:
|
||||
{
|
||||
struct ip6_frag_hdr * frag_hdr;
|
||||
struct ip6_frag_hdr *frag_hdr;
|
||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
|
||||
|
||||
frag_hdr = (struct ip6_frag_hdr *)p->payload;
|
||||
|
@ -707,7 +715,7 @@ netif_found:
|
|||
options_done:
|
||||
|
||||
/* p points to IPv6 header again. */
|
||||
pbuf_header_force(p, ip_data.current_ip_header_tot_len);
|
||||
pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len);
|
||||
|
||||
/* send to upper layers */
|
||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
|
||||
|
@ -781,11 +789,11 @@ ip6_input_cleanup:
|
|||
* used as source (usually during network startup). If the source IPv6 address it
|
||||
* IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
|
||||
* interface is filled in as source address. If the destination IPv6 address is
|
||||
* IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points
|
||||
* to it instead of the data.
|
||||
* LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
|
||||
* p->payload points to it instead of the data.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an
|
||||
protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
|
||||
IPv6 header and p->payload points to that IPv6 header)
|
||||
* @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
|
||||
* IP address of the netif is selected and used as source address.
|
||||
|
@ -805,7 +813,7 @@ ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
u8_t nexth, struct netif *netif)
|
||||
{
|
||||
const ip6_addr_t *src_used = src;
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
if (src != NULL && ip6_addr_isany(src)) {
|
||||
src = ip_2_ip6(ip6_select_source_address(netif, dest));
|
||||
if ((src == NULL) || ip6_addr_isany(src)) {
|
||||
|
@ -834,7 +842,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
|
||||
|
||||
/* Should the IPv6 header be generated or is it already included in p? */
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
/* generate IPv6 header */
|
||||
if (pbuf_header(p, IP6_HLEN)) {
|
||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
|
||||
|
@ -907,7 +915,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
* interface and calls upon ip6_output_if to do the actual work.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an
|
||||
protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
|
||||
IPv6 header and p->payload points to that IPv6 header)
|
||||
* @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
|
||||
* IP address of the netif is selected and used as source address.
|
||||
|
@ -930,7 +938,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
|
||||
LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
|
||||
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
netif = ip6_route(src, dest);
|
||||
} else {
|
||||
/* IP header included in p, read addresses. */
|
||||
|
@ -963,7 +971,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
* before calling ip6_output_if.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an
|
||||
protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
|
||||
IPv6 header and p->payload points to that IPv6 header)
|
||||
* @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
|
||||
* IP address of the netif is selected and used as source address.
|
||||
|
@ -989,7 +997,7 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
|
||||
LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
|
||||
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
netif = ip6_route(src, dest);
|
||||
} else {
|
||||
/* IP header included in p, read addresses. */
|
||||
|
@ -1033,9 +1041,9 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
|||
* @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
|
||||
*/
|
||||
err_t
|
||||
ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value)
|
||||
ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
|
||||
{
|
||||
struct ip6_hbh_hdr * hbh_hdr;
|
||||
struct ip6_hbh_hdr *hbh_hdr;
|
||||
|
||||
/* Move pointer to make room for hop-by-hop options header. */
|
||||
if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) {
|
||||
|
|
|
@ -73,7 +73,7 @@ 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;
|
||||
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 */
|
||||
|
@ -132,8 +132,8 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
|||
} 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'));
|
||||
(isdigit(*s) ? (u32_t)(*s - '0') :
|
||||
(u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
|
||||
} else {
|
||||
/* unexpected digit, space? CRLF? */
|
||||
break;
|
||||
|
@ -152,7 +152,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
|||
/* 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]);
|
||||
addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
|||
|
||||
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]);
|
||||
current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]);
|
||||
if ((current_block_index & 0x1) == 0) {
|
||||
current_block_value = current_block_value >> 16;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
|||
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]);
|
||||
next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]);
|
||||
if ((current_block_index & 0x1) == 0x01) {
|
||||
next_block_value = next_block_value >> 16;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
|||
{
|
||||
struct ip6_reassdata *prev;
|
||||
u16_t pbufs_freed = 0;
|
||||
u8_t clen;
|
||||
u16_t clen;
|
||||
struct pbuf *p;
|
||||
struct ip6_reass_helper *iprh;
|
||||
|
||||
|
@ -260,9 +260,10 @@ 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;
|
||||
struct ip6_frag_hdr *frag_hdr;
|
||||
u16_t offset, len;
|
||||
u8_t clen, valid = 1;
|
||||
u16_t clen;
|
||||
u8_t valid = 1;
|
||||
struct pbuf *q;
|
||||
|
||||
IP6_FRAG_STATS_INC(ip6_frag.recv);
|
||||
|
@ -278,12 +279,12 @@ ip6_reass(struct pbuf *p)
|
|||
|
||||
clen = pbuf_clen(p);
|
||||
|
||||
offset = ntohs(frag_hdr->_fragment_offset);
|
||||
offset = lwip_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 = lwip_ntohs(ip6_current_header()->_plen);
|
||||
len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN);
|
||||
len -= IP6_FRAG_HLEN;
|
||||
|
||||
|
@ -377,8 +378,9 @@ ip6_reass(struct pbuf *p)
|
|||
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);
|
||||
u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
|
||||
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||
}
|
||||
#else /* IPV6_FRAG_COPYHEADER */
|
||||
LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
|
||||
|
@ -528,8 +530,9 @@ ip6_reass(struct pbuf *p)
|
|||
#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);
|
||||
u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
|
||||
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||
}
|
||||
#endif
|
||||
pbuf_cat(ipr->p, next_pbuf);
|
||||
|
@ -544,8 +547,9 @@ ip6_reass(struct pbuf *p)
|
|||
#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);
|
||||
u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
|
||||
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||
}
|
||||
iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
|
||||
MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN);
|
||||
|
@ -559,7 +563,7 @@ ip6_reass(struct pbuf *p)
|
|||
- IP6_HLEN);
|
||||
|
||||
/* Set payload length in ip header. */
|
||||
iphdr_ptr->_plen = htons(ipr->datagram_len);
|
||||
iphdr_ptr->_plen = lwip_htons(ipr->datagram_len);
|
||||
|
||||
/* Get the first pbuf. */
|
||||
p = ipr->p;
|
||||
|
@ -609,6 +613,7 @@ nullreturn:
|
|||
|
||||
#if LWIP_IPV6 && LWIP_IPV6_FRAG
|
||||
|
||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
/** Allocate a new struct pbuf_custom_ref */
|
||||
static struct pbuf_custom_ref*
|
||||
ip6_frag_alloc_pbuf_custom_ref(void)
|
||||
|
@ -637,6 +642,7 @@ ip6_frag_free_pbuf_custom(struct pbuf *p)
|
|||
}
|
||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||
}
|
||||
#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
/**
|
||||
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
||||
|
@ -655,9 +661,13 @@ 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 ip6_frag_hdr *frag_hdr;
|
||||
struct pbuf *rambuf;
|
||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
struct pbuf *newpbuf;
|
||||
u16_t newpbuflen = 0;
|
||||
u16_t left_to_copy;
|
||||
#endif
|
||||
static u32_t identification;
|
||||
u16_t nfb;
|
||||
u16_t left, cop;
|
||||
|
@ -665,8 +675,6 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||
u16_t fragment_offset = 0;
|
||||
u16_t last;
|
||||
u16_t poff = IP6_HLEN;
|
||||
u16_t newpbuflen = 0;
|
||||
u16_t left_to_copy;
|
||||
|
||||
identification++;
|
||||
|
||||
|
@ -685,6 +693,26 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||
/* Fill this fragment */
|
||||
cop = last ? left : nfb;
|
||||
|
||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||
rambuf = pbuf_alloc(PBUF_IP, cop + 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!",
|
||||
(rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
|
||||
poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff);
|
||||
/* make room for the IP header */
|
||||
if (pbuf_header(rambuf, IP6_HLEN)) {
|
||||
pbuf_free(rambuf);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* fill in the IP header */
|
||||
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);
|
||||
#else
|
||||
/* 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,
|
||||
|
@ -696,7 +724,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("this needs a pbuf in one piece!",
|
||||
(p->len >= (IP6_HLEN + IP6_FRAG_HLEN)));
|
||||
(p->len >= (IP6_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);
|
||||
|
@ -743,12 +771,13 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||
}
|
||||
}
|
||||
poff = newpbuflen;
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
/* 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);
|
||||
frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
|
||||
frag_hdr->_identification = lwip_htonl(identification);
|
||||
|
||||
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
||||
IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
/**
|
||||
* @file
|
||||
* Multicast listener discovery
|
||||
*
|
||||
* @defgroup mld6 MLD6
|
||||
* @ingroup ip6
|
||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||
* No support for MLDv2.\n
|
||||
* To be called from TCPIP thread
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -37,14 +44,6 @@
|
|||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mld6 MLD6
|
||||
* @ingroup ip6
|
||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||
* No support for MLDv2.\n
|
||||
* To be called from TCPIP thread
|
||||
*/
|
||||
|
||||
/* Based on igmp.c implementation of igmp v2 protocol */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
@ -52,6 +51,7 @@
|
|||
#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/mld6.h"
|
||||
#include "lwip/prot/mld6.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
@ -75,16 +75,11 @@
|
|||
#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 struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr);
|
||||
static err_t mld6_remove_group(struct netif *netif, 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);
|
||||
static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -95,33 +90,21 @@ static void mld6_send(struct mld_group *group, u8_t type);
|
|||
err_t
|
||||
mld6_stop(struct netif *netif)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
struct mld_group *prev = NULL;
|
||||
struct mld_group *next;
|
||||
struct mld_group *group = netif_mld6_data(netif);
|
||||
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL);
|
||||
|
||||
/* 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;
|
||||
struct mld_group *next = group->next; /* avoid use-after-free below */
|
||||
|
||||
/* disable the group at the MAC level */
|
||||
if (netif->mld_mac_filter != NULL) {
|
||||
netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* free group */
|
||||
memp_free(MEMP_MLD6_GROUP, group);
|
||||
|
||||
/* move to "next" */
|
||||
group = next;
|
||||
}
|
||||
|
@ -136,12 +119,10 @@ mld6_stop(struct netif *netif)
|
|||
void
|
||||
mld6_report_groups(struct netif *netif)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
struct mld_group *group = netif_mld6_data(netif);
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->netif == netif) {
|
||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||
}
|
||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
@ -157,10 +138,10 @@ mld6_report_groups(struct netif *netif)
|
|||
struct mld_group *
|
||||
mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
struct mld_group *group = netif_mld6_data(ifp);
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) {
|
||||
if (ip6_addr_cmp(&(group->group_address), addr)) {
|
||||
return group;
|
||||
}
|
||||
group = group->next;
|
||||
|
@ -185,38 +166,37 @@ mld6_new_group(struct netif *ifp, const ip6_addr_t *addr)
|
|||
|
||||
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;
|
||||
group->next = netif_mld6_data(ifp);
|
||||
|
||||
mld_group_list = group;
|
||||
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a group in the mld_group_list and free
|
||||
* Remove a group from the mld_group_list, but do not free it yet
|
||||
*
|
||||
* @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)
|
||||
mld6_remove_group(struct netif *netif, struct mld_group *group)
|
||||
{
|
||||
err_t err = ERR_OK;
|
||||
|
||||
/* Is it the first group? */
|
||||
if (mld_group_list == group) {
|
||||
mld_group_list = group->next;
|
||||
if (netif_mld6_data(netif) == group) {
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next);
|
||||
} else {
|
||||
/* look for group further down the list */
|
||||
struct mld_group *tmpGroup;
|
||||
for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
||||
for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
||||
if (tmpGroup->next == group) {
|
||||
tmpGroup->next = group->next;
|
||||
break;
|
||||
|
@ -227,8 +207,6 @@ mld6_free_group(struct mld_group *group)
|
|||
err = ERR_ARG;
|
||||
}
|
||||
}
|
||||
/* free group */
|
||||
memp_free(MEMP_MLD6_GROUP, group);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -243,8 +221,8 @@ mld6_free_group(struct mld_group *group)
|
|||
void
|
||||
mld6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct mld_header * mld_hdr;
|
||||
struct mld_group* group;
|
||||
struct mld_header *mld_hdr;
|
||||
struct mld_group *group;
|
||||
|
||||
MLD6_STATS_INC(mld6.recv);
|
||||
|
||||
|
@ -266,10 +244,9 @@ mld6_input(struct pbuf *p, struct netif *inp)
|
|||
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;
|
||||
group = netif_mld6_data(inp);
|
||||
while (group != NULL) {
|
||||
if ((group->netif == inp) &&
|
||||
(!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
|
||||
if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
|
||||
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
|
||||
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
||||
}
|
||||
|
@ -373,12 +350,12 @@ mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
|
|||
|
||||
/* Activate this address on the MAC layer. */
|
||||
if (netif->mld_mac_filter != NULL) {
|
||||
netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
|
||||
netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* Report our membership. */
|
||||
MLD6_STATS_INC(mld6.tx_report);
|
||||
mld6_send(group, ICMP6_TYPE_MLR);
|
||||
mld6_send(netif, group, ICMP6_TYPE_MLR);
|
||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||
}
|
||||
|
||||
|
@ -440,19 +417,22 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
|
|||
if (group != NULL) {
|
||||
/* Leave if there is no other use of the group */
|
||||
if (group->use <= 1) {
|
||||
/* Remove the group from the list */
|
||||
mld6_remove_group(netif, group);
|
||||
|
||||
/* 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);
|
||||
mld6_send(netif, 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);
|
||||
netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* Free the group */
|
||||
mld6_free_group(group);
|
||||
/* free group struct */
|
||||
memp_free(MEMP_MLD6_GROUP, group);
|
||||
} else {
|
||||
/* Decrement group use */
|
||||
group->use--;
|
||||
|
@ -476,21 +456,26 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
|
|||
void
|
||||
mld6_tmr(void)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
struct netif *netif = netif_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;
|
||||
while (netif != NULL) {
|
||||
struct mld_group *group = netif_mld6_data(netif);
|
||||
|
||||
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(netif, group, ICMP6_TYPE_MLR);
|
||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||
}
|
||||
}
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
group = group->next;
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,11 +522,11 @@ mld6_delayed_report(struct mld_group *group, u16_t maxresp)
|
|||
* @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
|
||||
*/
|
||||
static void
|
||||
mld6_send(struct mld_group *group, u8_t type)
|
||||
mld6_send(struct netif *netif, struct mld_group *group, u8_t type)
|
||||
{
|
||||
struct mld_header * mld_hdr;
|
||||
struct pbuf * p;
|
||||
const ip6_addr_t * src_addr;
|
||||
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);
|
||||
|
@ -558,13 +543,13 @@ mld6_send(struct mld_group *group, u8_t type)
|
|||
}
|
||||
|
||||
/* Select our source address. */
|
||||
if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
|
||||
if (!ip6_addr_isvalid(netif_ip6_addr_state(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);
|
||||
src_addr = netif_ip6_addr(netif, 0);
|
||||
}
|
||||
|
||||
/* MLD message header pointer. */
|
||||
|
@ -579,7 +564,7 @@ mld6_send(struct mld_group *group, u8_t type)
|
|||
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
|
||||
|
||||
#if CHECKSUM_GEN_ICMP6
|
||||
IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
||||
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
|
||||
src_addr, &(group->group_address));
|
||||
}
|
||||
|
@ -591,7 +576,7 @@ mld6_send(struct mld_group *group, u8_t type)
|
|||
/* 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);
|
||||
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif);
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/priv/nd6_priv.h"
|
||||
#include "lwip/prot/nd6.h"
|
||||
#include "lwip/prot/icmp6.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
|
@ -57,9 +60,13 @@
|
|||
#include "lwip/mld6.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
|
||||
#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
|
||||
#endif
|
||||
|
||||
/* Router tables. */
|
||||
struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
|
||||
|
@ -82,23 +89,27 @@ static ip6_addr_t multicast_address;
|
|||
static u8_t nd6_ra_buffer[sizeof(struct prefix_option)];
|
||||
|
||||
/* Forward declarations. */
|
||||
static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr);
|
||||
static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr);
|
||||
static s8_t nd6_new_neighbor_cache_entry(void);
|
||||
static void nd6_free_neighbor_cache_entry(s8_t i);
|
||||
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr);
|
||||
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
|
||||
static s8_t nd6_new_destination_cache_entry(void);
|
||||
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif);
|
||||
static s8_t nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif);
|
||||
static s8_t nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif);
|
||||
static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif);
|
||||
static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif);
|
||||
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||
static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||
static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
|
||||
static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
|
||||
static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
||||
static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
||||
static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||
static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q);
|
||||
|
||||
#define ND6_SEND_FLAG_MULTICAST_DEST 0x01
|
||||
#define ND6_SEND_FLAG_ALLNODES_DEST 0x02
|
||||
static void nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags);
|
||||
static void nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags);
|
||||
static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
|
||||
static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
|
||||
static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags);
|
||||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
static err_t nd6_send_rs(struct netif * netif);
|
||||
static err_t nd6_send_rs(struct netif *netif);
|
||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||
|
||||
#if LWIP_ND6_QUEUEING
|
||||
|
@ -127,8 +138,8 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
switch (msg_type) {
|
||||
case ICMP6_TYPE_NA: /* Neighbor Advertisement. */
|
||||
{
|
||||
struct na_header * na_hdr;
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct na_header *na_hdr;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
|
||||
/* Check that na header fits in packet. */
|
||||
if (p->len < (sizeof(struct na_header))) {
|
||||
|
@ -143,10 +154,41 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
/* Unsolicited NA?*/
|
||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||
ip6_addr_t target_address;
|
||||
|
||||
/* This is an unsolicited NA.
|
||||
* link-layer changed?
|
||||
* part of DAD mechanism? */
|
||||
|
||||
/* Create an aligned copy. */
|
||||
ip6_addr_set(&target_address, &(na_hdr->target_address));
|
||||
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||
/* If the target address matches this netif, it is a DAD response. */
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
|
||||
ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) {
|
||||
/* We are using a duplicate address. */
|
||||
netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
|
||||
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/* Check to see if this address was autoconfigured. */
|
||||
if (!ip6_addr_islinklocal(&target_address)) {
|
||||
i = nd6_get_onlink_prefix(&target_address, inp);
|
||||
if (i >= 0) {
|
||||
/* Mark this prefix as duplicate, so that we don't use it
|
||||
* to generate this address again. */
|
||||
prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
|
||||
|
||||
/* Check that link-layer address option also fits in packet. */
|
||||
if (p->len < (sizeof(struct na_header) + 2)) {
|
||||
/* @todo debug message */
|
||||
|
@ -166,58 +208,25 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Override ip6_current_dest_addr() so that we have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address));
|
||||
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||
/* If the target address matches this netif, it is a DAD response. */
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
|
||||
ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
|
||||
/* We are using a duplicate address. */
|
||||
netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
|
||||
|
||||
#if LWIP_IPV6_MLD
|
||||
/* Leave solicited node multicast group. */
|
||||
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]);
|
||||
mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address);
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/* Check to see if this address was autoconfigured. */
|
||||
if (!ip6_addr_islinklocal(ip6_current_dest_addr())) {
|
||||
i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp);
|
||||
if (i >= 0) {
|
||||
/* Mark this prefix as duplicate, so that we don't use it
|
||||
* to generate this address again. */
|
||||
prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
|
||||
|
||||
/* This is an unsolicited NA, most likely there was a LLADDR change. */
|
||||
i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr());
|
||||
i = nd6_find_neighbor_cache_entry(&target_address);
|
||||
if (i >= 0) {
|
||||
if (na_hdr->flags & ND6_FLAG_OVERRIDE) {
|
||||
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ip6_addr_t target_address;
|
||||
|
||||
/* This is a solicited NA.
|
||||
* neighbor address resolution response?
|
||||
* neighbor unreachability detection response? */
|
||||
|
||||
/* Override ip6_current_dest_addr() so that we have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address));
|
||||
/* Create an aligned copy. */
|
||||
ip6_addr_set(&target_address, &(na_hdr->target_address));
|
||||
|
||||
/* Find the cache entry corresponding to this na. */
|
||||
i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr());
|
||||
i = nd6_find_neighbor_cache_entry(&target_address);
|
||||
if (i < 0) {
|
||||
/* We no longer care about this target address. drop it. */
|
||||
pbuf_free(p);
|
||||
|
@ -225,8 +234,6 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
|
||||
/* Update cache entry. */
|
||||
neighbor_cache[i].netif = inp;
|
||||
neighbor_cache[i].counter.reachable_time = reachable_time;
|
||||
if ((na_hdr->flags & ND6_FLAG_OVERRIDE) ||
|
||||
(neighbor_cache[i].state == ND6_INCOMPLETE)) {
|
||||
/* Check that link-layer address option also fits in packet. */
|
||||
|
@ -250,7 +257,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
|
||||
}
|
||||
|
||||
neighbor_cache[i].netif = inp;
|
||||
neighbor_cache[i].state = ND6_REACHABLE;
|
||||
neighbor_cache[i].counter.reachable_time = reachable_time;
|
||||
|
||||
/* Send queued packets, if any. */
|
||||
if (neighbor_cache[i].q != NULL) {
|
||||
|
@ -262,8 +272,8 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
case ICMP6_TYPE_NS: /* Neighbor solicitation. */
|
||||
{
|
||||
struct ns_header * ns_hdr;
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct ns_header *ns_hdr;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
u8_t accepted;
|
||||
|
||||
/* Check that ns header fits in packet. */
|
||||
|
@ -320,6 +330,8 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ip6_addr_t target_address;
|
||||
|
||||
/* Sender is trying to resolve our address. */
|
||||
/* Verify that they included their own link-layer address. */
|
||||
if (lladdr_opt == NULL) {
|
||||
|
@ -339,7 +351,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
/* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
||||
neighbor_cache[i].state = ND6_DELAY;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
|
||||
}
|
||||
} else {
|
||||
/* Add their IPv6 address and link-layer address to neighbor cache.
|
||||
|
@ -360,23 +372,27 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
/* Receiving a message does not prove reachability: only in one direction.
|
||||
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
||||
neighbor_cache[i].state = ND6_DELAY;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
|
||||
}
|
||||
|
||||
/* Override ip6_current_dest_addr() so that we have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address));
|
||||
/* Create an aligned copy. */
|
||||
ip6_addr_set(&target_address, &(ns_hdr->target_address));
|
||||
|
||||
/* Send back a NA for us. Allocate the reply pbuf. */
|
||||
nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE);
|
||||
nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE);
|
||||
}
|
||||
|
||||
break; /* ICMP6_TYPE_NS */
|
||||
}
|
||||
case ICMP6_TYPE_RA: /* Router Advertisement. */
|
||||
{
|
||||
struct ra_header * ra_hdr;
|
||||
u8_t * buffer; /* Used to copy options. */
|
||||
struct ra_header *ra_hdr;
|
||||
u8_t *buffer; /* Used to copy options. */
|
||||
u16_t offset;
|
||||
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||
/* There can by multiple RDNSS options per RA */
|
||||
u8_t rdnss_server_idx = 0;
|
||||
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
|
||||
|
||||
/* Check that RA header fits in packet. */
|
||||
if (p->len < sizeof(struct ra_header)) {
|
||||
|
@ -413,15 +429,15 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
|
||||
/* Re-set invalidation timer. */
|
||||
default_router_list[i].invalidation_timer = htons(ra_hdr->router_lifetime);
|
||||
default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime);
|
||||
|
||||
/* Re-set default timer values. */
|
||||
#if LWIP_ND6_ALLOW_RA_UPDATES
|
||||
if (ra_hdr->retrans_timer > 0) {
|
||||
retrans_timer = htonl(ra_hdr->retrans_timer);
|
||||
retrans_timer = lwip_htonl(ra_hdr->retrans_timer);
|
||||
}
|
||||
if (ra_hdr->reachable_time > 0) {
|
||||
reachable_time = htonl(ra_hdr->reachable_time);
|
||||
reachable_time = lwip_htonl(ra_hdr->reachable_time);
|
||||
}
|
||||
#endif /* LWIP_ND6_ALLOW_RA_UPDATES */
|
||||
|
||||
|
@ -441,7 +457,12 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
buffer = &((u8_t*)p->payload)[offset];
|
||||
} else {
|
||||
buffer = nd6_ra_buffer;
|
||||
pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset);
|
||||
if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) {
|
||||
pbuf_free(p);
|
||||
ND6_STATS_INC(nd6.lenerr);
|
||||
ND6_STATS_INC(nd6.drop);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (buffer[1] == 0) {
|
||||
/* zero-length extension. drop packet */
|
||||
|
@ -453,7 +474,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
switch (buffer[0]) {
|
||||
case ND6_OPTION_TYPE_SOURCE_LLADDR:
|
||||
{
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
lladdr_opt = (struct lladdr_option *)buffer;
|
||||
if ((default_router_list[i].neighbor_entry != NULL) &&
|
||||
(default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) {
|
||||
|
@ -465,35 +486,38 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
case ND6_OPTION_TYPE_MTU:
|
||||
{
|
||||
struct mtu_option * mtu_opt;
|
||||
struct mtu_option *mtu_opt;
|
||||
mtu_opt = (struct mtu_option *)buffer;
|
||||
if (htonl(mtu_opt->mtu) >= 1280) {
|
||||
if (lwip_htonl(mtu_opt->mtu) >= 1280) {
|
||||
#if LWIP_ND6_ALLOW_RA_UPDATES
|
||||
inp->mtu = (u16_t)htonl(mtu_opt->mtu);
|
||||
inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu);
|
||||
#endif /* LWIP_ND6_ALLOW_RA_UPDATES */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ND6_OPTION_TYPE_PREFIX_INFO:
|
||||
{
|
||||
struct prefix_option * prefix_opt;
|
||||
struct prefix_option *prefix_opt;
|
||||
prefix_opt = (struct prefix_option *)buffer;
|
||||
|
||||
if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) {
|
||||
if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) &&
|
||||
(prefix_opt->prefix_length == 64) &&
|
||||
!ip6_addr_islinklocal(&(prefix_opt->prefix))) {
|
||||
/* Add to on-link prefix list. */
|
||||
s8_t prefix;
|
||||
ip6_addr_t prefix_addr;
|
||||
|
||||
/* Get a memory-aligned copy of the prefix. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix));
|
||||
ip6_addr_set(&prefix_addr, &(prefix_opt->prefix));
|
||||
|
||||
/* find cache entry for this prefix. */
|
||||
prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp);
|
||||
prefix = nd6_get_onlink_prefix(&prefix_addr, inp);
|
||||
if (prefix < 0) {
|
||||
/* Create a new cache entry. */
|
||||
prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp);
|
||||
prefix = nd6_new_onlink_prefix(&prefix_addr, inp);
|
||||
}
|
||||
if (prefix >= 0) {
|
||||
prefix_list[prefix].invalidation_timer = htonl(prefix_opt->valid_lifetime);
|
||||
prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime);
|
||||
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) {
|
||||
|
@ -513,6 +537,37 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
route_opt = (struct route_option *)buffer;*/
|
||||
|
||||
break;
|
||||
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||
case ND6_OPTION_TYPE_RDNSS:
|
||||
{
|
||||
u8_t num, n;
|
||||
struct rdnss_option * rdnss_opt;
|
||||
|
||||
rdnss_opt = (struct rdnss_option *)buffer;
|
||||
num = (rdnss_opt->length - 1) / 2;
|
||||
for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
|
||||
ip_addr_t rdnss_address;
|
||||
|
||||
/* Get a memory-aligned copy of the prefix. */
|
||||
ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]);
|
||||
|
||||
if (htonl(rdnss_opt->lifetime) > 0) {
|
||||
/* TODO implement Lifetime > 0 */
|
||||
dns_setserver(rdnss_server_idx++, &rdnss_address);
|
||||
} else {
|
||||
/* TODO implement DNS removal in dns.c */
|
||||
u8_t s;
|
||||
for (s = 0; s < DNS_MAX_SERVERS; s++) {
|
||||
const ip_addr_t *addr = dns_getserver(s);
|
||||
if(ip_addr_cmp(addr, &rdnss_address)) {
|
||||
dns_setserver(s, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
|
||||
default:
|
||||
/* Unrecognized option, abort. */
|
||||
ND6_STATS_INC(nd6.proterr);
|
||||
|
@ -526,8 +581,9 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
case ICMP6_TYPE_RD: /* Redirect */
|
||||
{
|
||||
struct redirect_header * redir_hdr;
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct redirect_header *redir_hdr;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
ip6_addr_t tmp;
|
||||
|
||||
/* Check that Redir header fits in packet. */
|
||||
if (p->len < sizeof(struct redirect_header)) {
|
||||
|
@ -550,10 +606,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
|
||||
/* Copy original destination address to current source address, to have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address));
|
||||
ip6_addr_set(&tmp, &(redir_hdr->destination_address));
|
||||
|
||||
/* Find dest address in cache */
|
||||
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
|
||||
i = nd6_find_destination_cache_entry(&tmp);
|
||||
if (i < 0) {
|
||||
/* Destination not in cache, drop packet. */
|
||||
pbuf_free(p);
|
||||
|
@ -567,20 +623,20 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
if (lladdr_opt != NULL) {
|
||||
if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
|
||||
/* Copy target address to current source address, to have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address));
|
||||
ip6_addr_set(&tmp, &(redir_hdr->target_address));
|
||||
|
||||
i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
|
||||
i = nd6_find_neighbor_cache_entry(&tmp);
|
||||
if (i < 0) {
|
||||
i = nd6_new_neighbor_cache_entry();
|
||||
if (i >= 0) {
|
||||
neighbor_cache[i].netif = inp;
|
||||
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
|
||||
ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
|
||||
ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp);
|
||||
|
||||
/* Receiving a message does not prove reachability: only in one direction.
|
||||
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
||||
neighbor_cache[i].state = ND6_DELAY;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
|
||||
}
|
||||
}
|
||||
if (i >= 0) {
|
||||
|
@ -589,7 +645,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
/* Receiving a message does not prove reachability: only in one direction.
|
||||
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
||||
neighbor_cache[i].state = ND6_DELAY;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -599,8 +655,9 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
case ICMP6_TYPE_PTB: /* Packet too big */
|
||||
{
|
||||
struct icmp6_hdr *icmp6hdr; /* Packet too big message */
|
||||
struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */
|
||||
struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
|
||||
u32_t pmtu;
|
||||
ip6_addr_t tmp;
|
||||
|
||||
/* Check that ICMPv6 header + IPv6 header fit in payload */
|
||||
if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) {
|
||||
|
@ -615,10 +672,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr));
|
||||
|
||||
/* Copy original destination address to current source address, to have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest));
|
||||
ip6_addr_set(&tmp, &(ip6hdr->dest));
|
||||
|
||||
/* Look for entry in destination cache. */
|
||||
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
|
||||
i = nd6_find_destination_cache_entry(&tmp);
|
||||
if (i < 0) {
|
||||
/* Destination not in cache, drop packet. */
|
||||
pbuf_free(p);
|
||||
|
@ -626,7 +683,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
|
||||
/* Change the Path MTU. */
|
||||
pmtu = htonl(icmp6hdr->data);
|
||||
pmtu = lwip_htonl(icmp6hdr->data);
|
||||
destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF);
|
||||
|
||||
break; /* ICMP6_TYPE_PTB */
|
||||
|
@ -655,7 +712,7 @@ void
|
|||
nd6_tmr(void)
|
||||
{
|
||||
s8_t i;
|
||||
struct netif * netif;
|
||||
struct netif *netif;
|
||||
|
||||
/* Process neighbor entries. */
|
||||
for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
|
||||
|
@ -668,7 +725,7 @@ nd6_tmr(void)
|
|||
} else {
|
||||
/* Send a NS for this entry. */
|
||||
neighbor_cache[i].counter.probes_sent++;
|
||||
nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST);
|
||||
nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
|
||||
}
|
||||
break;
|
||||
case ND6_REACHABLE:
|
||||
|
@ -685,15 +742,15 @@ nd6_tmr(void)
|
|||
}
|
||||
break;
|
||||
case ND6_STALE:
|
||||
neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL;
|
||||
neighbor_cache[i].counter.stale_time++;
|
||||
break;
|
||||
case ND6_DELAY:
|
||||
if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) {
|
||||
if (neighbor_cache[i].counter.delay_time <= 1) {
|
||||
/* Change to PROBE state. */
|
||||
neighbor_cache[i].state = ND6_PROBE;
|
||||
neighbor_cache[i].counter.probes_sent = 0;
|
||||
} else {
|
||||
neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL;
|
||||
neighbor_cache[i].counter.delay_time--;
|
||||
}
|
||||
break;
|
||||
case ND6_PROBE:
|
||||
|
@ -704,7 +761,7 @@ nd6_tmr(void)
|
|||
} else {
|
||||
/* Send a NS for this entry. */
|
||||
neighbor_cache[i].counter.probes_sent++;
|
||||
nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0);
|
||||
nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0);
|
||||
}
|
||||
break;
|
||||
case ND6_NO_ENTRY:
|
||||
|
@ -738,7 +795,7 @@ nd6_tmr(void)
|
|||
|
||||
/* Process prefix entries. */
|
||||
for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
|
||||
if (prefix_list[i].netif != NULL) {
|
||||
if (prefix_list[i].netif != NULL) {
|
||||
if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) {
|
||||
/* Entry timed out, remove it */
|
||||
prefix_list[i].invalidation_timer = 0;
|
||||
|
@ -794,7 +851,7 @@ nd6_tmr(void)
|
|||
}
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -803,18 +860,11 @@ nd6_tmr(void)
|
|||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
|
||||
u8_t addr_state = netif_ip6_addr_state(netif, i);
|
||||
if (ip6_addr_istentative(addr_state)) {
|
||||
if ((addr_state & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) {
|
||||
if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) {
|
||||
/* No NA received in response. Mark address as valid. */
|
||||
netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
|
||||
/* @todo implement preferred and valid lifetimes. */
|
||||
} else if (netif->flags & NETIF_FLAG_UP) {
|
||||
#if LWIP_IPV6_MLD
|
||||
if ((addr_state & 0x07) == 0) {
|
||||
/* Join solicited node multicast group. */
|
||||
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]);
|
||||
mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address);
|
||||
}
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
/* Send a NS for this address. */
|
||||
nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST);
|
||||
/* tentative: set next state by increasing by one */
|
||||
|
@ -840,6 +890,17 @@ nd6_tmr(void)
|
|||
|
||||
}
|
||||
|
||||
/** Send a neighbor solicitation message for a specific neighbor cache entry
|
||||
*
|
||||
* @param entry the neightbor cache entry for wich to send the message
|
||||
* @param flags one of ND6_SEND_FLAG_*
|
||||
*/
|
||||
static void
|
||||
nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags)
|
||||
{
|
||||
nd6_send_ns(entry->netif, &entry->next_hop_address, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a neighbor solicitation message
|
||||
*
|
||||
|
@ -848,11 +909,11 @@ nd6_tmr(void)
|
|||
* @param flags one of ND6_SEND_FLAG_*
|
||||
*/
|
||||
static void
|
||||
nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
|
||||
nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
|
||||
{
|
||||
struct ns_header * ns_hdr;
|
||||
struct pbuf * p;
|
||||
const ip6_addr_t * src_addr;
|
||||
struct ns_header *ns_hdr;
|
||||
struct pbuf *p;
|
||||
const ip6_addr_t *src_addr;
|
||||
u16_t lladdr_opt_len;
|
||||
|
||||
if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) {
|
||||
|
@ -917,13 +978,13 @@ nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
|
|||
* @param flags one of ND6_SEND_FLAG_*
|
||||
*/
|
||||
static void
|
||||
nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
|
||||
nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
|
||||
{
|
||||
struct na_header * na_hdr;
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct pbuf * p;
|
||||
const ip6_addr_t * src_addr;
|
||||
const ip6_addr_t * dest_addr;
|
||||
struct na_header *na_hdr;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
struct pbuf *p;
|
||||
const ip6_addr_t *src_addr;
|
||||
const ip6_addr_t *dest_addr;
|
||||
u16_t lladdr_opt_len;
|
||||
|
||||
/* Use link-local address as source address. */
|
||||
|
@ -988,12 +1049,12 @@ nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
|
|||
* @param netif the netif on which to send the message
|
||||
*/
|
||||
static err_t
|
||||
nd6_send_rs(struct netif * netif)
|
||||
nd6_send_rs(struct netif *netif)
|
||||
{
|
||||
struct rs_header * rs_hdr;
|
||||
struct lladdr_option * lladdr_opt;
|
||||
struct pbuf * p;
|
||||
const ip6_addr_t * src_addr;
|
||||
struct rs_header *rs_hdr;
|
||||
struct lladdr_option *lladdr_opt;
|
||||
struct pbuf *p;
|
||||
const ip6_addr_t *src_addr;
|
||||
err_t err;
|
||||
u16_t lladdr_opt_len = 0;
|
||||
|
||||
|
@ -1059,7 +1120,7 @@ nd6_send_rs(struct netif * netif)
|
|||
* entry is found
|
||||
*/
|
||||
static s8_t
|
||||
nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr)
|
||||
nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr)
|
||||
{
|
||||
s8_t i;
|
||||
for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
|
||||
|
@ -1218,7 +1279,7 @@ nd6_free_neighbor_cache_entry(s8_t i)
|
|||
* entry is found
|
||||
*/
|
||||
static s8_t
|
||||
nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr)
|
||||
nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr)
|
||||
{
|
||||
s8_t i;
|
||||
for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
|
||||
|
@ -1261,6 +1322,22 @@ nd6_new_destination_cache_entry(void)
|
|||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the destination cache.
|
||||
*
|
||||
* This operation may be necessary for consistency in the light of changing
|
||||
* local addresses and/or use of the gateway hook.
|
||||
*/
|
||||
void
|
||||
nd6_clear_destination_cache(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
|
||||
ip6_addr_set_any(&destination_cache[i].destination_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an address matches an on-link prefix.
|
||||
*
|
||||
|
@ -1268,7 +1345,7 @@ nd6_new_destination_cache_entry(void)
|
|||
* @return 1 if the address is on-link, 0 otherwise
|
||||
*/
|
||||
static s8_t
|
||||
nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif)
|
||||
nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
|
||||
|
@ -1296,8 +1373,8 @@ nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
* @return the default router entry index, or -1 if no suitable
|
||||
* router is found
|
||||
*/
|
||||
s8_t
|
||||
nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif)
|
||||
static s8_t
|
||||
nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
/* last_router is used for round-robin router selection (as recommended
|
||||
|
@ -1348,6 +1425,30 @@ nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a router-announced route to the given destination.
|
||||
*
|
||||
* The caller is responsible for checking whether the returned netif, if any,
|
||||
* is in a suitable state (up, link up) to be used for packet transmission.
|
||||
*
|
||||
* @param ip6addr the destination IPv6 address
|
||||
* @return the netif to use for the destination, or NULL if none found
|
||||
*/
|
||||
struct netif *
|
||||
nd6_find_route(const ip6_addr_t *ip6addr)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
i = nd6_select_router(ip6addr, NULL);
|
||||
if (i >= 0) {
|
||||
if (default_router_list[i].neighbor_entry != NULL) {
|
||||
return default_router_list[i].neighbor_entry->netif; /* may be NULL */
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an entry for a default router.
|
||||
*
|
||||
|
@ -1356,7 +1457,7 @@ nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
* @return the index of the router entry, or -1 if not found
|
||||
*/
|
||||
static s8_t
|
||||
nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif)
|
||||
nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
|
@ -1381,9 +1482,10 @@ nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif)
|
|||
* @return the index on the router table, or -1 if could not be created
|
||||
*/
|
||||
static s8_t
|
||||
nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif)
|
||||
nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
|
||||
{
|
||||
s8_t router_index;
|
||||
s8_t free_router_index;
|
||||
s8_t neighbor_index;
|
||||
|
||||
/* Do we have a neighbor entry for this router? */
|
||||
|
@ -1399,19 +1501,30 @@ nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif)
|
|||
neighbor_cache[neighbor_index].netif = netif;
|
||||
neighbor_cache[neighbor_index].q = NULL;
|
||||
neighbor_cache[neighbor_index].state = ND6_INCOMPLETE;
|
||||
neighbor_cache[neighbor_index].counter.probes_sent = 0;
|
||||
neighbor_cache[neighbor_index].counter.probes_sent = 1;
|
||||
nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST);
|
||||
}
|
||||
|
||||
/* Mark neighbor as router. */
|
||||
neighbor_cache[neighbor_index].isrouter = 1;
|
||||
|
||||
/* Look for empty entry. */
|
||||
for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) {
|
||||
free_router_index = LWIP_ND6_NUM_ROUTERS;
|
||||
for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) {
|
||||
/* check if router already exists (this is a special case for 2 netifs on the same subnet
|
||||
- e.g. wifi and cable) */
|
||||
if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){
|
||||
return router_index;
|
||||
}
|
||||
if (default_router_list[router_index].neighbor_entry == NULL) {
|
||||
default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
|
||||
return router_index;
|
||||
/* remember lowest free index to create a new entry */
|
||||
free_router_index = router_index;
|
||||
}
|
||||
}
|
||||
if (free_router_index < LWIP_ND6_NUM_ROUTERS) {
|
||||
default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
|
||||
return free_router_index;
|
||||
}
|
||||
|
||||
/* Could not create a router entry. */
|
||||
|
||||
|
@ -1430,7 +1543,7 @@ nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif)
|
|||
* @return the index on the prefix table, or -1 if not found
|
||||
*/
|
||||
static s8_t
|
||||
nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif)
|
||||
nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
|
@ -1454,7 +1567,7 @@ nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif)
|
|||
* @return the index on the prefix table, or -1 if not created
|
||||
*/
|
||||
static s8_t
|
||||
nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif)
|
||||
nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
|
@ -1488,9 +1601,12 @@ nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif)
|
|||
* suitable next hop was found, ERR_MEM if no cache entry
|
||||
* could be created
|
||||
*/
|
||||
s8_t
|
||||
nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif)
|
||||
static s8_t
|
||||
nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||
{
|
||||
#ifdef LWIP_HOOK_ND6_GET_GW
|
||||
const ip6_addr_t *next_hop_addr;
|
||||
#endif /* LWIP_HOOK_ND6_GET_GW */
|
||||
s8_t i;
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
|
@ -1534,6 +1650,12 @@ nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
/* Destination in local link. */
|
||||
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
|
||||
ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
|
||||
#ifdef LWIP_HOOK_ND6_GET_GW
|
||||
} else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) {
|
||||
/* Next hop for destination provided by hook function. */
|
||||
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
|
||||
ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr);
|
||||
#endif /* LWIP_HOOK_ND6_GET_GW */
|
||||
} else {
|
||||
/* We need to select a router. */
|
||||
i = nd6_select_router(ip6addr, netif);
|
||||
|
@ -1583,7 +1705,8 @@ nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
neighbor_cache[i].isrouter = 0;
|
||||
neighbor_cache[i].netif = netif;
|
||||
neighbor_cache[i].state = ND6_INCOMPLETE;
|
||||
neighbor_cache[i].counter.probes_sent = 0;
|
||||
neighbor_cache[i].counter.probes_sent = 1;
|
||||
nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,8 +1723,8 @@ nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
* @param q packet to be queued
|
||||
* @return ERR_OK if succeeded, ERR_MEM if out of memory
|
||||
*/
|
||||
err_t
|
||||
nd6_queue_packet(s8_t neighbor_index, struct pbuf * q)
|
||||
static err_t
|
||||
nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
|
||||
{
|
||||
err_t result = ERR_MEM;
|
||||
struct pbuf *p;
|
||||
|
@ -1736,6 +1859,7 @@ static void
|
|||
nd6_send_q(s8_t i)
|
||||
{
|
||||
struct ip6_hdr *ip6hdr;
|
||||
ip6_addr_t dest;
|
||||
#if LWIP_ND6_QUEUEING
|
||||
struct nd6_q_entry *q;
|
||||
#endif /* LWIP_ND6_QUEUEING */
|
||||
|
@ -1752,10 +1876,10 @@ nd6_send_q(s8_t i)
|
|||
neighbor_cache[i].q = q->next;
|
||||
/* Get ipv6 header. */
|
||||
ip6hdr = (struct ip6_hdr *)(q->p->payload);
|
||||
/* Override ip6_current_dest_addr() so that we have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest));
|
||||
/* Create an aligned copy. */
|
||||
ip6_addr_set(&dest, &(ip6hdr->dest));
|
||||
/* send the queued IPv6 packet */
|
||||
(neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr());
|
||||
(neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(q->p);
|
||||
/* now queue entry can be freed */
|
||||
|
@ -1765,10 +1889,10 @@ nd6_send_q(s8_t i)
|
|||
if (neighbor_cache[i].q != NULL) {
|
||||
/* Get ipv6 header. */
|
||||
ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload);
|
||||
/* Override ip6_current_dest_addr() so that we have an aligned copy. */
|
||||
ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest));
|
||||
/* Create an aligned copy. */
|
||||
ip6_addr_set(&dest, &(ip6hdr->dest));
|
||||
/* send the queued IPv6 packet */
|
||||
(neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr());
|
||||
(neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(neighbor_cache[i].q);
|
||||
neighbor_cache[i].q = NULL;
|
||||
|
@ -1776,6 +1900,61 @@ nd6_send_q(s8_t i)
|
|||
#endif /* LWIP_ND6_QUEUEING */
|
||||
}
|
||||
|
||||
/**
|
||||
* A packet is to be transmitted to a specific IPv6 destination on a specific
|
||||
* interface. Check if we can find the hardware address of the next hop to use
|
||||
* for the packet. If so, give the hardware address to the caller, which should
|
||||
* use it to send the packet right away. Otherwise, enqueue the packet for
|
||||
* later transmission while looking up the hardware address, if possible.
|
||||
*
|
||||
* As such, this function returns one of three different possible results:
|
||||
*
|
||||
* - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now.
|
||||
* - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later.
|
||||
* - not ERR_OK: something went wrong; forward the error upward in the stack.
|
||||
*
|
||||
* @param netif The lwIP network interface on which the IP packet will be sent.
|
||||
* @param q The pbuf(s) containing the IP packet to be sent.
|
||||
* @param ip6addr The destination IPv6 address of the packet.
|
||||
* @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning
|
||||
* the packet has been queued).
|
||||
* @return
|
||||
* - ERR_OK on success, ERR_RTE if no route was found for the packet,
|
||||
* or ERR_MEM if low memory conditions prohibit sending the packet at all.
|
||||
*/
|
||||
err_t
|
||||
nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
/* Get next hop record. */
|
||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
||||
if (i < 0) {
|
||||
/* failed to get a next hop neighbor record. */
|
||||
return i;
|
||||
}
|
||||
|
||||
/* 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 / ND6_TMR_INTERVAL;
|
||||
}
|
||||
/* @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)) {
|
||||
|
||||
/* Tell the caller to send out the packet now. */
|
||||
*hwaddrp = neighbor_cache[i].lladdr;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* We should queue packet on this interface. */
|
||||
*hwaddrp = NULL;
|
||||
return nd6_queue_packet(i, q);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Path MTU for a destination.
|
||||
|
@ -1785,7 +1964,7 @@ nd6_send_q(s8_t i)
|
|||
* @return the Path MTU, if known, or the netif default MTU
|
||||
*/
|
||||
u16_t
|
||||
nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif)
|
||||
nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
|
@ -1815,7 +1994,7 @@ nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif)
|
|||
* by an upper layer protocol (TCP)
|
||||
*/
|
||||
void
|
||||
nd6_reachability_hint(const ip6_addr_t * ip6addr)
|
||||
nd6_reachability_hint(const ip6_addr_t *ip6addr)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
|
@ -1858,7 +2037,7 @@ nd6_reachability_hint(const ip6_addr_t * ip6addr)
|
|||
* @param netif points to a network interface
|
||||
*/
|
||||
void
|
||||
nd6_cleanup_netif(struct netif * netif)
|
||||
nd6_cleanup_netif(struct netif *netif)
|
||||
{
|
||||
u8_t i;
|
||||
s8_t router_index;
|
||||
|
@ -1882,4 +2061,38 @@ nd6_cleanup_netif(struct netif * netif)
|
|||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6_MLD
|
||||
/**
|
||||
* The state of a local IPv6 address entry is about to change. If needed, join
|
||||
* or leave the solicited-node multicast group for the address.
|
||||
*
|
||||
* @param netif The netif that owns the address.
|
||||
* @param addr_idx The index of the address.
|
||||
* @param new_state The new (IP6_ADDR_) state for the address.
|
||||
*/
|
||||
void
|
||||
nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state)
|
||||
{
|
||||
u8_t old_state, old_member, new_member;
|
||||
|
||||
old_state = netif_ip6_addr_state(netif, addr_idx);
|
||||
|
||||
/* Determine whether we were, and should be, a member of the solicited-node
|
||||
* multicast group for this address. For tentative addresses, the group is
|
||||
* not joined until the address enters the TENTATIVE_1 (or VALID) state. */
|
||||
old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE);
|
||||
new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE);
|
||||
|
||||
if (old_member != new_member) {
|
||||
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]);
|
||||
|
||||
if (new_member) {
|
||||
mld6_joingroup_netif(netif, &multicast_address);
|
||||
} else {
|
||||
mld6_leavegroup_netif(netif, &multicast_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
|
|
@ -2,6 +2,28 @@
|
|||
* @file
|
||||
* Common functions used throughout the stack.
|
||||
*
|
||||
* 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_htons(x) your_htons
|
||||
* \#define lwip_htonl(x) your_htonl
|
||||
*
|
||||
* Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts.
|
||||
*
|
||||
* If you \#define them to htons() and htonl(), you should
|
||||
* \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
|
||||
* defining htonx/ntohx compatibility macros.
|
||||
|
||||
* @defgroup sys_nonstandard Non-standard functions
|
||||
* @ingroup sys_layer
|
||||
* lwIP provides default implementations for non-standard functions.
|
||||
* These can be mapped to OS functions to reduce code footprint if desired.
|
||||
* All defines related to this section must not be placed in lwipopts.h,
|
||||
* but in arch/cc.h!
|
||||
* These options cannot be \#defined in lwipopts.h since they are not options
|
||||
* of lwIP itself, but options of the lwIP port to your system.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -39,21 +61,11 @@
|
|||
#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.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
#if !defined(lwip_htons)
|
||||
/**
|
||||
* Convert an u16_t from host- to network byte order.
|
||||
*
|
||||
|
@ -63,21 +75,11 @@
|
|||
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);
|
||||
return (u16_t)PP_HTONS(n);
|
||||
}
|
||||
#endif /* lwip_htons */
|
||||
|
||||
#if !defined(lwip_htonl)
|
||||
/**
|
||||
* Convert an u32_t from host- to network byte order.
|
||||
*
|
||||
|
@ -87,22 +89,134 @@ lwip_ntohs(u16_t n)
|
|||
u32_t
|
||||
lwip_htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000UL) >> 8) |
|
||||
((n & 0xff000000UL) >> 24);
|
||||
return (u32_t)PP_HTONL(n);
|
||||
}
|
||||
#endif /* lwip_htonl */
|
||||
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
||||
#ifndef lwip_strnstr
|
||||
/**
|
||||
* Convert an u32_t from network- to host byte order.
|
||||
*
|
||||
* @param n u32_t in network byte order
|
||||
* @return n in host byte order
|
||||
* @ingroup sys_nonstandard
|
||||
* lwIP default implementation for strnstr() non-standard function.
|
||||
* This can be \#defined to strnstr() depending on your platform port.
|
||||
*/
|
||||
u32_t
|
||||
lwip_ntohl(u32_t n)
|
||||
char*
|
||||
lwip_strnstr(const char* buffer, const char* token, size_t n)
|
||||
{
|
||||
return lwip_htonl(n);
|
||||
const char* p;
|
||||
size_t tokenlen = strlen(token);
|
||||
if (tokenlen == 0) {
|
||||
return LWIP_CONST_CAST(char *, buffer);
|
||||
}
|
||||
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
|
||||
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
|
||||
return LWIP_CONST_CAST(char *, p);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
||||
#ifndef lwip_stricmp
|
||||
/**
|
||||
* @ingroup sys_nonstandard
|
||||
* lwIP default implementation for stricmp() non-standard function.
|
||||
* This can be \#defined to stricmp() depending on your platform port.
|
||||
*/
|
||||
int
|
||||
lwip_stricmp(const char* str1, const char* str2)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *str1++;
|
||||
c2 = *str2++;
|
||||
if (c1 != c2) {
|
||||
char c1_upc = c1 | 0x20;
|
||||
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
|
||||
/* characters are not equal an one is in the alphabet range:
|
||||
downcase both chars and check again */
|
||||
char c2_upc = c2 | 0x20;
|
||||
if (c1_upc != c2_upc) {
|
||||
/* still not equal */
|
||||
/* don't care for < or > */
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* characters are not equal but none is in the alphabet range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (c1 != 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef lwip_strnicmp
|
||||
/**
|
||||
* @ingroup sys_nonstandard
|
||||
* lwIP default implementation for strnicmp() non-standard function.
|
||||
* This can be \#defined to strnicmp() depending on your platform port.
|
||||
*/
|
||||
int
|
||||
lwip_strnicmp(const char* str1, const char* str2, size_t len)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *str1++;
|
||||
c2 = *str2++;
|
||||
if (c1 != c2) {
|
||||
char c1_upc = c1 | 0x20;
|
||||
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
|
||||
/* characters are not equal an one is in the alphabet range:
|
||||
downcase both chars and check again */
|
||||
char c2_upc = c2 | 0x20;
|
||||
if (c1_upc != c2_upc) {
|
||||
/* still not equal */
|
||||
/* don't care for < or > */
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* characters are not equal but none is in the alphabet range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (len-- && c1 != 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef lwip_itoa
|
||||
/**
|
||||
* @ingroup sys_nonstandard
|
||||
* lwIP default implementation for itoa() non-standard function.
|
||||
* This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port.
|
||||
*/
|
||||
void
|
||||
lwip_itoa(char* result, size_t bufsize, int number)
|
||||
{
|
||||
const int base = 10;
|
||||
char* ptr = result, *ptr1 = result, tmp_char;
|
||||
int tmp_value;
|
||||
LWIP_UNUSED_ARG(bufsize);
|
||||
|
||||
do {
|
||||
tmp_value = number;
|
||||
number /= base;
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)];
|
||||
} while(number);
|
||||
|
||||
/* Apply negative sign */
|
||||
if (tmp_value < 0) {
|
||||
*ptr++ = '-';
|
||||
}
|
||||
*ptr-- = '\0';
|
||||
while(ptr1 < ptr) {
|
||||
tmp_char = *ptr;
|
||||
*ptr--= *ptr1;
|
||||
*ptr1++ = tmp_char;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,37 @@
|
|||
/**
|
||||
* @file
|
||||
* DNS - host name to IP address resolver.
|
||||
*
|
||||
* @defgroup dns DNS
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* Implements a DNS host name to IP address resolver.
|
||||
*
|
||||
* The lwIP DNS resolver functions are used to lookup a host name and
|
||||
* map it to a numerical IP address. It maintains a list of resolved
|
||||
* hostnames that can be queried with the dns_lookup() function.
|
||||
* New hostnames can be resolved using the dns_query() function.
|
||||
*
|
||||
* The lwIP version of the resolver also adds a non-blocking version of
|
||||
* gethostbyname() that will work with a raw API application. This function
|
||||
* checks for an IP address string first and converts it if it is valid.
|
||||
* gethostbyname() then does a dns_lookup() to see if the name is
|
||||
* already in the table. If so, the IP is returned. If not, a query is
|
||||
* issued and the function returns with a ERR_INPROGRESS status. The app
|
||||
* using the dns client must then go into a waiting state.
|
||||
*
|
||||
* Once a hostname has been resolved (or found to be non-existent),
|
||||
* the resolver code calls a specified callback function (which
|
||||
* must be implemented by the module that uses the resolver).
|
||||
*
|
||||
* Multicast DNS queries are supported for names ending on ".local".
|
||||
* However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762
|
||||
* chapter 5.1), this is not a fully compliant implementation of continuous
|
||||
* mDNS querying!
|
||||
*
|
||||
* All functions must be called from TCPIP thread.
|
||||
*
|
||||
* @see @ref netconn_common for thread-safe access.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -37,34 +68,6 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup dns DNS
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* Implements a DNS host name to IP address resolver.
|
||||
*
|
||||
* The lwIP DNS resolver functions are used to lookup a host name and
|
||||
* map it to a numerical IP address. It maintains a list of resolved
|
||||
* hostnames that can be queried with the dns_lookup() function.
|
||||
* New hostnames can be resolved using the dns_query() function.
|
||||
*
|
||||
* The lwIP version of the resolver also adds a non-blocking version of
|
||||
* gethostbyname() that will work with a raw API application. This function
|
||||
* checks for an IP address string first and converts it if it is valid.
|
||||
* gethostbyname() then does a dns_lookup() to see if the name is
|
||||
* already in the table. If so, the IP is returned. If not, a query is
|
||||
* issued and the function returns with a ERR_INPROGRESS status. The app
|
||||
* using the dns client must then go into a waiting state.
|
||||
*
|
||||
* Once a hostname has been resolved (or found to be non-existent),
|
||||
* the resolver code calls a specified callback function (which
|
||||
* must be implemented by the module that uses the resolver).
|
||||
*
|
||||
* All functions must be called from TCPIP thread.
|
||||
*
|
||||
* @see @ref netconn_common for thread-safe access.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* RFC 1035 - Domain names - implementation and specification
|
||||
* RFC 2181 - Clarifications to the DNS Specification
|
||||
|
@ -73,6 +76,7 @@
|
|||
/** @todo: define good default values (rfc compliance) */
|
||||
/** @todo: improve answer parsing, more checkings... */
|
||||
/** @todo: check RFC1035 - 7.3. Processing responses */
|
||||
/** @todo: one-shot mDNS: dual-stack fallback to another IP version */
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Includes
|
||||
|
@ -82,10 +86,12 @@
|
|||
|
||||
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/prot/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -104,11 +110,6 @@ static u16_t dns_txid;
|
|||
#define DNS_PORT_ALLOWED(port) ((port) >= 1024)
|
||||
#endif
|
||||
|
||||
/** DNS server port address */
|
||||
#ifndef DNS_SERVER_PORT
|
||||
#define DNS_SERVER_PORT 53
|
||||
#endif
|
||||
|
||||
/** DNS maximum number of retries when asking for a name, before "timeout". */
|
||||
#ifndef DNS_MAX_RETRIES
|
||||
#define DNS_MAX_RETRIES 4
|
||||
|
@ -121,6 +122,13 @@ static u16_t dns_txid;
|
|||
#error DNS_MAX_TTL must be a positive 32-bit value
|
||||
#endif
|
||||
|
||||
#if DNS_TABLE_SIZE > 255
|
||||
#error DNS_TABLE_SIZE must fit into an u8_t
|
||||
#endif
|
||||
#if DNS_MAX_SERVERS > 255
|
||||
#error DNS_MAX_SERVERS must fit into an u8_t
|
||||
#endif
|
||||
|
||||
/* The number of parallel requests (i.e. calls to dns_gethostbyname
|
||||
* that cannot be answered from the DNS table.
|
||||
* This is set to the table size by default.
|
||||
|
@ -128,6 +136,10 @@ static u16_t dns_txid;
|
|||
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
|
||||
#ifndef DNS_MAX_REQUESTS
|
||||
#define DNS_MAX_REQUESTS DNS_TABLE_SIZE
|
||||
#else
|
||||
#if DNS_MAX_REQUESTS > 255
|
||||
#error DNS_MAX_REQUESTS must fit into an u8_t
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
/* In this configuration, both arrays have to have the same size and are used
|
||||
|
@ -139,6 +151,10 @@ static u16_t dns_txid;
|
|||
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
|
||||
#ifndef DNS_MAX_SOURCE_PORTS
|
||||
#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
|
||||
#else
|
||||
#if DNS_MAX_SOURCE_PORTS > 255
|
||||
#error DNS_MAX_SOURCE_PORTS must fit into an u8_t
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#ifdef DNS_MAX_SOURCE_PORTS
|
||||
|
@ -165,70 +181,11 @@ static u16_t dns_txid;
|
|||
#define LWIP_DNS_SET_ADDRTYPE(x, y)
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
/** DNS field TYPE used for "Resource Records" */
|
||||
#define DNS_RRTYPE_A 1 /* a host address */
|
||||
#define DNS_RRTYPE_NS 2 /* an authoritative name server */
|
||||
#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */
|
||||
#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */
|
||||
#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */
|
||||
#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */
|
||||
#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */
|
||||
#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */
|
||||
#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */
|
||||
#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */
|
||||
#define DNS_RRTYPE_WKS 11 /* a well known service description */
|
||||
#define DNS_RRTYPE_PTR 12 /* a domain name pointer */
|
||||
#define DNS_RRTYPE_HINFO 13 /* host information */
|
||||
#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */
|
||||
#define DNS_RRTYPE_MX 15 /* mail exchange */
|
||||
#define DNS_RRTYPE_TXT 16 /* text strings */
|
||||
#define DNS_RRTYPE_AAAA 28 /* IPv6 address */
|
||||
|
||||
/** DNS field CLASS used for "Resource Records" */
|
||||
#define DNS_RRCLASS_IN 1 /* the Internet */
|
||||
#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
|
||||
#define DNS_RRCLASS_CH 3 /* the CHAOS class */
|
||||
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
|
||||
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
|
||||
|
||||
/* DNS protocol flags */
|
||||
#define DNS_FLAG1_RESPONSE 0x80
|
||||
#define DNS_FLAG1_OPCODE_STATUS 0x10
|
||||
#define DNS_FLAG1_OPCODE_INVERSE 0x08
|
||||
#define DNS_FLAG1_OPCODE_STANDARD 0x00
|
||||
#define DNS_FLAG1_AUTHORATIVE 0x04
|
||||
#define DNS_FLAG1_TRUNC 0x02
|
||||
#define DNS_FLAG1_RD 0x01
|
||||
#define DNS_FLAG2_RA 0x80
|
||||
#define DNS_FLAG2_ERR_MASK 0x0f
|
||||
#define DNS_FLAG2_ERR_NONE 0x00
|
||||
#define DNS_FLAG2_ERR_NAME 0x03
|
||||
|
||||
/* DNS protocol states */
|
||||
#define DNS_STATE_UNUSED 0
|
||||
#define DNS_STATE_NEW 1
|
||||
#define DNS_STATE_ASKING 2
|
||||
#define DNS_STATE_DONE 3
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
#define LWIP_DNS_ISMDNS_ARG(x) , x
|
||||
#else
|
||||
#define LWIP_DNS_ISMDNS_ARG(x)
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** DNS message header */
|
||||
struct dns_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FLD_8(u8_t flags1);
|
||||
PACK_STRUCT_FLD_8(u8_t flags2);
|
||||
PACK_STRUCT_FIELD(u16_t numquestions);
|
||||
PACK_STRUCT_FIELD(u16_t numanswers);
|
||||
PACK_STRUCT_FIELD(u16_t numauthrr);
|
||||
PACK_STRUCT_FIELD(u16_t numextrarr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_DNS_HDR 12
|
||||
|
||||
/** DNS query message structure.
|
||||
No packing needed: only used locally on the stack. */
|
||||
|
@ -254,6 +211,14 @@ struct dns_answer {
|
|||
/* maximum allowed size for the struct due to non-packed */
|
||||
#define SIZEOF_DNS_ANSWER_ASSERT 12
|
||||
|
||||
/* DNS table entry states */
|
||||
typedef enum {
|
||||
DNS_STATE_UNUSED = 0,
|
||||
DNS_STATE_NEW = 1,
|
||||
DNS_STATE_ASKING = 2,
|
||||
DNS_STATE_DONE = 3
|
||||
} dns_state_enum_t;
|
||||
|
||||
/** DNS table entry */
|
||||
struct dns_table_entry {
|
||||
u32_t ttl;
|
||||
|
@ -271,6 +236,9 @@ struct dns_table_entry {
|
|||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
u8_t reqaddrtype;
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
u8_t is_mdns;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** DNS request table entry: used when dns_gehostbyname cannot answer the
|
||||
|
@ -334,39 +302,12 @@ static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
|
|||
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
|
||||
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
|
||||
|
||||
#ifndef LWIP_DNS_STRICMP
|
||||
#define LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2)
|
||||
/**
|
||||
* A small but sufficient implementation for case insensitive strcmp.
|
||||
* This can be defined to e.g. stricmp for windows or strcasecmp for linux. */
|
||||
static int
|
||||
dns_stricmp(const char* str1, const char* str2)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *str1++;
|
||||
c2 = *str2++;
|
||||
if (c1 != c2) {
|
||||
char c1_upc = c1 | 0x20;
|
||||
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
|
||||
/* characters are not equal an one is in the alphabet range:
|
||||
downcase both chars and check again */
|
||||
char c2_upc = c2 | 0x20;
|
||||
if (c1_upc != c2_upc) {
|
||||
/* still not equal */
|
||||
/* don't care for < or > */
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* characters are not equal but none is in the alphabet range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (c1 != 0);
|
||||
return 0;
|
||||
}
|
||||
#endif /* LWIP_DNS_STRICMP */
|
||||
#if LWIP_IPV4
|
||||
const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Initialize the resolver: set up the UDP pcb and configure the default server
|
||||
|
@ -504,7 +445,7 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_
|
|||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
while (entry != NULL) {
|
||||
if ((LWIP_DNS_STRICMP(entry->name, hostname) == 0) &&
|
||||
if ((lwip_stricmp(entry->name, hostname) == 0) &&
|
||||
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) {
|
||||
if (addr) {
|
||||
ip_addr_copy(*addr, entry->addr);
|
||||
|
@ -516,7 +457,7 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_
|
|||
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
size_t i;
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
|
||||
if ((LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) &&
|
||||
if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) &&
|
||||
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) {
|
||||
if (addr) {
|
||||
ip_addr_copy(*addr, local_hostlist_static[i].addr);
|
||||
|
@ -546,7 +487,7 @@ dns_local_removehost(const char *hostname, const ip_addr_t *addr)
|
|||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
struct local_hostlist_entry *last_entry = NULL;
|
||||
while (entry != NULL) {
|
||||
if (((hostname == NULL) || !LWIP_DNS_STRICMP(entry->name, hostname)) &&
|
||||
if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) &&
|
||||
((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
|
||||
struct local_hostlist_entry *free_entry;
|
||||
if (last_entry != NULL) {
|
||||
|
@ -635,7 +576,7 @@ dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addr
|
|||
/* Walk through name list, return entry if found. If not, return NULL. */
|
||||
for (i = 0; i < DNS_TABLE_SIZE; ++i) {
|
||||
if ((dns_table[i].state == DNS_STATE_DONE) &&
|
||||
(LWIP_DNS_STRICMP(name, dns_table[i].name) == 0) &&
|
||||
(lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) &&
|
||||
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
|
||||
ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
|
||||
|
@ -664,11 +605,14 @@ dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addr
|
|||
static u16_t
|
||||
dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset)
|
||||
{
|
||||
unsigned char n;
|
||||
int n;
|
||||
u16_t response_offset = start_offset;
|
||||
|
||||
do {
|
||||
n = pbuf_get_at(p, response_offset++);
|
||||
n = pbuf_try_get_at(p, response_offset++);
|
||||
if (n < 0) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
/** @see RFC 1035 - 4.1.4. Message compression */
|
||||
if ((n & 0xc0) == 0xc0) {
|
||||
/* Compressed name: cannot be equal since we don't send them */
|
||||
|
@ -676,7 +620,11 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset)
|
|||
} else {
|
||||
/* Not compressed name */
|
||||
while (n > 0) {
|
||||
if ((*query) != pbuf_get_at(p, response_offset)) {
|
||||
int c = pbuf_try_get_at(p, response_offset);
|
||||
if (c < 0) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
if ((*query) != (u8_t)c) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
++response_offset;
|
||||
|
@ -685,7 +633,11 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset)
|
|||
}
|
||||
++query;
|
||||
}
|
||||
} while (pbuf_get_at(p, response_offset) != 0);
|
||||
n = pbuf_try_get_at(p, response_offset);
|
||||
if (n < 0) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
} while (n != 0);
|
||||
|
||||
return response_offset + 1;
|
||||
}
|
||||
|
@ -698,26 +650,34 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset)
|
|||
* @return index to end of the name
|
||||
*/
|
||||
static u16_t
|
||||
dns_parse_name(struct pbuf* p, u16_t query_idx)
|
||||
dns_skip_name(struct pbuf* p, u16_t query_idx)
|
||||
{
|
||||
unsigned char n;
|
||||
int n;
|
||||
u16_t offset = query_idx;
|
||||
|
||||
do {
|
||||
n = pbuf_get_at(p, query_idx++);
|
||||
n = pbuf_try_get_at(p, offset++);
|
||||
if (n < 0) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
/** @see RFC 1035 - 4.1.4. Message compression */
|
||||
if ((n & 0xc0) == 0xc0) {
|
||||
/* Compressed name */
|
||||
/* Compressed name: since we only want to skip it (not check it), stop here */
|
||||
break;
|
||||
} else {
|
||||
/* Not compressed name */
|
||||
while (n > 0) {
|
||||
++query_idx;
|
||||
--n;
|
||||
if (offset + n >= p->tot_len) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
offset = (u16_t)(offset + n);
|
||||
}
|
||||
} while (pbuf_get_at(p, query_idx) != 0);
|
||||
n = pbuf_try_get_at(p, offset);
|
||||
if (n < 0) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
} while (n != 0);
|
||||
|
||||
return query_idx + 1;
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -742,7 +702,11 @@ dns_send(u8_t idx)
|
|||
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
|
||||
(u16_t)(entry->server_idx), entry->name));
|
||||
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
|
||||
if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
|
||||
if (ip_addr_isany_val(dns_servers[entry->server_idx])
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
&& !entry->is_mdns
|
||||
#endif
|
||||
) {
|
||||
/* DNS server not valid anymore, e.g. PPP netif has been shut down */
|
||||
/* call specified callback function if provided */
|
||||
dns_call_found(idx, NULL);
|
||||
|
@ -755,9 +719,11 @@ dns_send(u8_t idx)
|
|||
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
|
||||
SIZEOF_DNS_QUERY), PBUF_RAM);
|
||||
if (p != NULL) {
|
||||
const ip_addr_t* dst;
|
||||
u16_t dst_port;
|
||||
/* fill dns header */
|
||||
memset(&hdr, 0, SIZEOF_DNS_HDR);
|
||||
hdr.id = htons(entry->txid);
|
||||
hdr.id = lwip_htons(entry->txid);
|
||||
hdr.flags1 = DNS_FLAG1_RD;
|
||||
hdr.numquestions = PP_HTONS(1);
|
||||
pbuf_take(p, &hdr, SIZEOF_DNS_HDR);
|
||||
|
@ -797,7 +763,30 @@ dns_send(u8_t idx)
|
|||
/* send dns packet */
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
|
||||
entry->txid, entry->name, entry->server_idx));
|
||||
err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT);
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
if (entry->is_mdns) {
|
||||
dst_port = DNS_MQUERY_PORT;
|
||||
#if LWIP_IPV6
|
||||
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
|
||||
{
|
||||
dst = &dns_mquery_v6group;
|
||||
}
|
||||
#endif
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
else
|
||||
#endif
|
||||
#if LWIP_IPV4
|
||||
{
|
||||
dst = &dns_mquery_v4group;
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||
{
|
||||
dst_port = DNS_SERVER_PORT;
|
||||
dst = &dns_servers[entry->server_idx];
|
||||
}
|
||||
err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
|
||||
|
||||
/* free pbuf */
|
||||
pbuf_free(p);
|
||||
|
@ -982,12 +971,9 @@ dns_check_entry(u8_t i)
|
|||
LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
|
||||
|
||||
switch (entry->state) {
|
||||
|
||||
case DNS_STATE_NEW: {
|
||||
u16_t txid;
|
||||
case DNS_STATE_NEW:
|
||||
/* initialize new entry */
|
||||
txid = dns_create_txid();
|
||||
entry->txid = txid;
|
||||
entry->txid = dns_create_txid();
|
||||
entry->state = DNS_STATE_ASKING;
|
||||
entry->server_idx = 0;
|
||||
entry->tmr = 1;
|
||||
|
@ -1000,12 +986,14 @@ dns_check_entry(u8_t i)
|
|||
("dns_send returned error: %s\n", lwip_strerr(err)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_STATE_ASKING:
|
||||
if (--entry->tmr == 0) {
|
||||
if (++entry->retries == DNS_MAX_RETRIES) {
|
||||
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
|
||||
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
&& !entry->is_mdns
|
||||
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||
) {
|
||||
/* change of server */
|
||||
entry->server_idx++;
|
||||
entry->tmr = 1;
|
||||
|
@ -1095,8 +1083,6 @@ dns_correct_response(u8_t idx, u32_t ttl)
|
|||
}
|
||||
/**
|
||||
* Receive input function for DNS response packets arriving for the dns UDP pcb.
|
||||
*
|
||||
* @params see udp.h
|
||||
*/
|
||||
static void
|
||||
dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
|
@ -1123,7 +1109,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
/* copy dns payload inside static buffer for processing */
|
||||
if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) {
|
||||
/* Match the ID in the DNS header with the name table. */
|
||||
txid = htons(hdr.id);
|
||||
txid = lwip_htons(hdr.id);
|
||||
for (i = 0; i < DNS_TABLE_SIZE; i++) {
|
||||
const struct dns_table_entry *entry = &dns_table[i];
|
||||
if ((entry->state == DNS_STATE_ASKING) &&
|
||||
|
@ -1131,8 +1117,8 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
|
||||
/* We only care about the question(s) and the answers. The authrr
|
||||
and the extrarr are simply discarded. */
|
||||
nquestions = htons(hdr.numquestions);
|
||||
nanswers = htons(hdr.numanswers);
|
||||
nquestions = lwip_htons(hdr.numquestions);
|
||||
nanswers = lwip_htons(hdr.numanswers);
|
||||
|
||||
/* Check for correct response. */
|
||||
if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) {
|
||||
|
@ -1144,10 +1130,15 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
|
||||
/* Check whether response comes from the same network address to which the
|
||||
question was sent. (RFC 5452) */
|
||||
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
|
||||
goto memerr; /* ignore this packet */
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
if (!entry->is_mdns)
|
||||
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||
{
|
||||
/* Check whether response comes from the same network address to which the
|
||||
question was sent. (RFC 5452) */
|
||||
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the name in the "question" part match with the name in the entry and
|
||||
|
@ -1159,7 +1150,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
}
|
||||
|
||||
/* check if "question" part matches the request */
|
||||
pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx);
|
||||
if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) ||
|
||||
(LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) ||
|
||||
(!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) {
|
||||
|
@ -1175,11 +1168,17 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
} else {
|
||||
while ((nanswers > 0) && (res_idx < p->tot_len)) {
|
||||
/* skip answer resource record's host name */
|
||||
res_idx = dns_parse_name(p, res_idx);
|
||||
res_idx = dns_skip_name(p, res_idx);
|
||||
if (res_idx == 0xFFFF) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
|
||||
/* Check for IP address type and Internet class. Others are discarded. */
|
||||
pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx);
|
||||
if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
res_idx += SIZEOF_DNS_ANSWER;
|
||||
|
||||
if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) {
|
||||
#if LWIP_IPV4
|
||||
if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) {
|
||||
|
@ -1189,11 +1188,13 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
{
|
||||
ip4_addr_t ip4addr;
|
||||
/* read the IP address after answer resource record's header */
|
||||
pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx);
|
||||
if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr);
|
||||
pbuf_free(p);
|
||||
/* handle correct response */
|
||||
dns_correct_response(i, ntohl(ans.ttl));
|
||||
dns_correct_response(i, lwip_ntohl(ans.ttl));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1206,18 +1207,23 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||
{
|
||||
ip6_addr_t ip6addr;
|
||||
/* read the IP address after answer resource record's header */
|
||||
pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx);
|
||||
if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr);
|
||||
pbuf_free(p);
|
||||
/* handle correct response */
|
||||
dns_correct_response(i, ntohl(ans.ttl));
|
||||
dns_correct_response(i, lwip_ntohl(ans.ttl));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
}
|
||||
/* skip this answer */
|
||||
res_idx += htons(ans.len);
|
||||
if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) {
|
||||
goto memerr; /* ignore this packet */
|
||||
}
|
||||
res_idx += lwip_htons(ans.len);
|
||||
--nanswers;
|
||||
}
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
|
@ -1260,11 +1266,11 @@ memerr:
|
|||
* @param hostnamelen length of the hostname
|
||||
* @param found a callback function to be called on success, failure or timeout
|
||||
* @param callback_arg argument to pass to the callback function
|
||||
* @return @return a err_t return code.
|
||||
* @return err_t return code.
|
||||
*/
|
||||
static err_t
|
||||
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
||||
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
|
||||
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns))
|
||||
{
|
||||
u8_t i;
|
||||
u8_t lseq, lseqi;
|
||||
|
@ -1277,7 +1283,7 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|||
/* check for duplicate entries */
|
||||
for (i = 0; i < DNS_TABLE_SIZE; i++) {
|
||||
if ((dns_table[i].state == DNS_STATE_ASKING) &&
|
||||
(LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) {
|
||||
(lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) {
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
if (dns_table[i].reqaddrtype != dns_addrtype) {
|
||||
/* requested address types don't match
|
||||
|
@ -1313,8 +1319,9 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|||
}
|
||||
/* check if this is the oldest completed entry */
|
||||
if (entry->state == DNS_STATE_DONE) {
|
||||
if ((u8_t)(dns_seqno - entry->seqno) > lseq) {
|
||||
lseq = dns_seqno - entry->seqno;
|
||||
u8_t age = dns_seqno - entry->seqno;
|
||||
if (age > lseq) {
|
||||
lseq = age;
|
||||
lseqi = i;
|
||||
}
|
||||
}
|
||||
|
@ -1379,6 +1386,10 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|||
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
|
||||
#endif
|
||||
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
entry->is_mdns = is_mdns;
|
||||
#endif
|
||||
|
||||
dns_seqno++;
|
||||
|
||||
/* force to send query without waiting timer */
|
||||
|
@ -1424,7 +1435,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
|
|||
* @param found a callback function to be called on success, failure or timeout (only if
|
||||
* ERR_INPROGRESS is returned!)
|
||||
* @param callback_arg argument to pass to the callback function
|
||||
* @param dns_addrtype: - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
|
||||
* @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
|
||||
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
|
||||
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
|
||||
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
|
||||
|
@ -1434,6 +1445,9 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|||
void *callback_arg, u8_t dns_addrtype)
|
||||
{
|
||||
size_t hostnamelen;
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
u8_t is_mdns;
|
||||
#endif
|
||||
/* not initialized or no valid server yet, or invalid addr pointer
|
||||
* or invalid hostname or invalid hostname length */
|
||||
if ((addr == NULL) ||
|
||||
|
@ -1490,13 +1504,25 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|||
LWIP_UNUSED_ARG(dns_addrtype);
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
/* prevent calling found callback if no server is set, return error instead */
|
||||
if (ip_addr_isany_val(dns_servers[0])) {
|
||||
return ERR_VAL;
|
||||
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||
if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) {
|
||||
is_mdns = 1;
|
||||
} else {
|
||||
is_mdns = 0;
|
||||
}
|
||||
|
||||
if (!is_mdns)
|
||||
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||
{
|
||||
/* prevent calling found callback if no server is set, return error instead */
|
||||
if (ip_addr_isany_val(dns_servers[0])) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* queue query with specified callback */
|
||||
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
|
||||
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)
|
||||
LWIP_DNS_ISMDNS_ARG(is_mdns));
|
||||
}
|
||||
|
||||
#endif /* LWIP_DNS */
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
/**
|
||||
* @file
|
||||
* Incluse internet checksum functions.
|
||||
* Incluse internet checksum functions.\n
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -42,20 +51,8 @@
|
|||
#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
|
||||
|
@ -110,10 +107,10 @@ lwip_standard_chksum(const void *dataptr, int len)
|
|||
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.
|
||||
/* This maybe a little confusing: reorder sum using lwip_htons()
|
||||
instead of lwip_ntohs() since it has a little less call overhead.
|
||||
The caller must invert bits for Internet sum ! */
|
||||
return htons((u16_t)acc);
|
||||
return lwip_htons((u16_t)acc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -285,8 +282,8 @@ inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
|
|||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
acc += (u32_t)lwip_htons((u16_t)proto);
|
||||
acc += (u32_t)lwip_htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is probably faster than if statements... */
|
||||
|
@ -431,8 +428,8 @@ inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
|
|||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
acc += (u32_t)lwip_htons((u16_t)proto);
|
||||
acc += (u32_t)lwip_htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is probably faster than if statements... */
|
||||
|
|
|
@ -35,27 +35,6 @@
|
|||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
|
||||
* @ingroup lwip
|
||||
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
|
||||
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
|
||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
||||
* context and put them into a queue which is processed from mainloop.\n
|
||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
||||
* Porting: implement all functions in @ref sys_time and @ref sys_prot.\n
|
||||
* You can only use @ref callbackstyle_api in this mode.
|
||||
*
|
||||
* @defgroup lwip_os OS mode (TCPIP thread)
|
||||
* @ingroup lwip
|
||||
* Use this mode if you run an OS on your system. It is recommended to
|
||||
* use an RTOS that correctly handles priority inversion and
|
||||
* to use LWIP_TCPIP_CORE_LOCKING.\n
|
||||
* Porting: implement all functions in @ref sys_layer.\n
|
||||
* You can use @ref callbackstyle_api together with \#define tcpip_callback,
|
||||
* and all @ref threadsafe_api.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
|
@ -70,7 +49,6 @@
|
|||
#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/timeouts.h"
|
||||
|
@ -83,6 +61,25 @@
|
|||
#include "netif/ppp/ppp_opts.h"
|
||||
#include "netif/ppp/ppp_impl.h"
|
||||
|
||||
#ifndef LWIP_SKIP_PACKING_CHECK
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct packed_struct_test
|
||||
{
|
||||
PACK_STRUCT_FLD_8(u8_t dummy1);
|
||||
PACK_STRUCT_FIELD(u32_t dummy2);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5
|
||||
|
||||
#endif
|
||||
|
||||
/* Compile-time sanity checks for configuration errors.
|
||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||
*/
|
||||
|
@ -144,7 +141,7 @@
|
|||
#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))
|
||||
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
|
||||
#error "The maximum valid window scale value is 14!"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
||||
|
@ -222,7 +219,7 @@
|
|||
#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"
|
||||
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)"
|
||||
#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"
|
||||
|
@ -230,9 +227,6 @@
|
|||
#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"
|
||||
|
@ -325,10 +319,10 @@
|
|||
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
|
||||
#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
|
||||
#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
|
||||
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (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 !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
|
||||
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (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
|
||||
|
@ -345,6 +339,15 @@
|
|||
void
|
||||
lwip_init(void)
|
||||
{
|
||||
#ifndef LWIP_SKIP_CONST_CHECK
|
||||
int a;
|
||||
LWIP_UNUSED_ARG(a);
|
||||
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||
#endif
|
||||
#ifndef LWIP_SKIP_PACKING_CHECK
|
||||
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
|
||||
#endif
|
||||
|
||||
/* Modules initialization */
|
||||
stats_init();
|
||||
#if !NO_SYS
|
||||
|
@ -369,9 +372,6 @@ lwip_init(void)
|
|||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_AUTOIP
|
||||
autoip_init();
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_IGMP
|
||||
igmp_init();
|
||||
#endif /* LWIP_IGMP */
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
/**
|
||||
* @file ip.c
|
||||
* @file
|
||||
* Common IPv4 and IPv6 code
|
||||
*
|
||||
* @defgroup ip IP
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* @defgroup ip4 IPv4
|
||||
* @ingroup ip
|
||||
*
|
||||
* @defgroup ip6 IPv6
|
||||
* @ingroup ip
|
||||
*
|
||||
* @defgroup ipaddr IP address handling
|
||||
* @ingroup infrastructure
|
||||
*
|
||||
* @defgroup ip4addr IPv4 only
|
||||
* @ingroup ipaddr
|
||||
*
|
||||
* @defgroup ip6addr IPv6 only
|
||||
* @ingroup ipaddr
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -36,23 +53,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ip4 IPv4
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* @defgroup ip6 IPv6
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* @defgroup ipaddr IP address handling
|
||||
* @ingroup infrastructure
|
||||
*
|
||||
* @defgroup ip4addr IPv4 only
|
||||
* @ingroup ipaddr
|
||||
*
|
||||
* @defgroup ip6addr IPv6 only
|
||||
* @ingroup ipaddr
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV4 || LWIP_IPV6
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
* 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
|
||||
* MEMP_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
|
||||
|
@ -54,15 +54,20 @@
|
|||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if MEM_LIBC_MALLOC
|
||||
#include <stdlib.h> /* for malloc()/free() */
|
||||
#endif
|
||||
|
||||
#if MEM_LIBC_MALLOC || MEM_USE_POOLS
|
||||
|
||||
/** mem_init is not used when using pools instead of a heap or using
|
||||
* C library malloc().
|
||||
*/
|
||||
|
@ -161,17 +166,26 @@ void *
|
|||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
void *ret;
|
||||
struct memp_malloc_helper *element;
|
||||
struct memp_malloc_helper *element = NULL;
|
||||
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) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
||||
MEM_STATS_INC(err);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -180,20 +194,6 @@ again:
|
|||
MEM_STATS_INC(err);
|
||||
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 */
|
||||
MEM_STATS_INC(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* save the pool number this element came from */
|
||||
element->poolnr = poolnr;
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
*
|
||||
* lwIP has dedicated pools for many structures (netconn, protocol control blocks,
|
||||
* packet buffers, ...). All these pools are managed here.
|
||||
*
|
||||
* @defgroup mempool Memory pools
|
||||
* @ingroup infrastructure
|
||||
* Custom memory pools
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -38,12 +43,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mempool Memory pools
|
||||
* @ingroup infrastructure
|
||||
* Custom memory pools
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
|
@ -72,7 +71,7 @@
|
|||
#include "netif/ppp/ppp_opts.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/priv/nd6_priv.h"
|
||||
#include "lwip/ip6_frag.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
|
@ -120,14 +119,14 @@ memp_sanity(const struct memp_desc *desc)
|
|||
* (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
|
||||
* @param desc the pool p comes from
|
||||
*/
|
||||
static void
|
||||
memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc)
|
||||
{
|
||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
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) {
|
||||
|
@ -136,7 +135,10 @@ memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *des
|
|||
LWIP_ASSERT(errstr, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||
LWIP_UNUSED_ARG(p);
|
||||
LWIP_UNUSED_ARG(desc);
|
||||
#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,14 +146,14 @@ memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *des
|
|||
* (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
|
||||
* @param desc the pool p comes from
|
||||
*/
|
||||
static void
|
||||
memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc)
|
||||
{
|
||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
||||
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) {
|
||||
|
@ -160,7 +162,10 @@ memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *de
|
|||
LWIP_ASSERT(errstr, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
|
||||
LWIP_UNUSED_ARG(p);
|
||||
LWIP_UNUSED_ARG(desc);
|
||||
#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,6 +174,7 @@ memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *de
|
|||
static void
|
||||
memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
|
||||
{
|
||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
u8_t *m;
|
||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
||||
|
@ -178,6 +184,10 @@ memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
|
|||
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
||||
memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
#endif
|
||||
#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||
LWIP_UNUSED_ARG(p);
|
||||
LWIP_UNUSED_ARG(desc);
|
||||
#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||
}
|
||||
|
||||
#if MEMP_OVERFLOW_CHECK >= 2
|
||||
|
@ -195,34 +205,16 @@ memp_overflow_check_all(void)
|
|||
SYS_ARCH_PROTECT(old_level);
|
||||
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
p = (struct memp *)(size_t)(memp_pools[i]->base);
|
||||
p = (struct memp*)LWIP_MEM_ALIGN(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);
|
||||
p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||
|
||||
#if !MEMP_MEM_MALLOC
|
||||
/**
|
||||
* Initialize the restricted areas of all memp elements in a pool.
|
||||
*/
|
||||
static void
|
||||
memp_overflow_init(const struct memp_desc *desc)
|
||||
{
|
||||
u16_t i;
|
||||
struct memp *p;
|
||||
|
||||
p = (struct memp*)LWIP_MEM_ALIGN(desc->base);
|
||||
for (i = 0; i < desc->num; ++i) {
|
||||
memp_overflow_init_element(p, desc);
|
||||
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
}
|
||||
}
|
||||
#endif /* !MEMP_MEM_MALLOC */
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
|
||||
/**
|
||||
|
@ -246,6 +238,9 @@ memp_init_pool(const struct memp_desc *desc)
|
|||
for (i = 0; i < desc->num; ++i) {
|
||||
memp->next = *desc->tab;
|
||||
*desc->tab = memp;
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
memp_overflow_init_element(memp, desc);
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
/* cast through void* to get rid of alignment warnings */
|
||||
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
|
@ -253,21 +248,14 @@ memp_init_pool(const struct memp_desc *desc)
|
|||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
memp_overflow_init(desc);
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
#endif /* !MEMP_MEM_MALLOC */
|
||||
|
||||
#if MEMP_STATS
|
||||
#if !MEMP_MEM_MALLOC
|
||||
desc->stats->avail = desc->num;
|
||||
#endif /* MEMP_STATS */
|
||||
#endif /* !MEMP_MEM_MALLOC */
|
||||
|
||||
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
|
||||
#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
|
||||
desc->stats->name = desc->desc;
|
||||
#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */
|
||||
#endif /* MEMP_STATS */
|
||||
#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,15 +301,15 @@ do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int
|
|||
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 */
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
if (memp != NULL) {
|
||||
#if !MEMP_MEM_MALLOC
|
||||
#if MEMP_OVERFLOW_CHECK == 1
|
||||
memp_overflow_check_element_overflow(memp, desc);
|
||||
memp_overflow_check_element_underflow(memp, desc);
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
|
||||
*desc->tab = memp->next;
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
memp->next = NULL;
|
||||
|
@ -483,12 +471,16 @@ memp_free(memp_t type, void *mem)
|
|||
|
||||
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
|
||||
|
||||
if (mem == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if MEMP_OVERFLOW_CHECK >= 2
|
||||
memp_overflow_check_all();
|
||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||
|
||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
||||
old_first = memp_pools[type].tab;
|
||||
old_first = *memp_pools[type]->tab;
|
||||
#endif
|
||||
|
||||
do_memp_free_pool(memp_pools[type], mem);
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
/**
|
||||
* @file
|
||||
* lwIP network interface abstraction
|
||||
*
|
||||
* @defgroup netif Network interface (NETIF)
|
||||
* @ingroup callbackstyle_api
|
||||
*
|
||||
* @defgroup netif_ip4 IPv4 address handling
|
||||
* @ingroup netif
|
||||
*
|
||||
* @defgroup netif_ip6 IPv6 address handling
|
||||
* @ingroup netif
|
||||
*
|
||||
* @defgroup netif_cd Client data handling
|
||||
* Store data (void*) on a netif for application usage.
|
||||
* @see @ref LWIP_NUM_NETIF_CLIENT_DATA
|
||||
* @ingroup netif
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -34,31 +48,31 @@
|
|||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup netif Network interface (NETIF)
|
||||
* @ingroup callbackstyle_api
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip.h"
|
||||
#if ENABLE_LOOPBACK
|
||||
#include "lwip/sys.h"
|
||||
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
#include "lwip/tcpip.h"
|
||||
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#include "netif/lwip_ethernet.h"
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
#include "lwip/autoip.h"
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
@ -92,6 +106,10 @@ struct netif *netif_default;
|
|||
|
||||
static u8_t netif_num;
|
||||
|
||||
#if LWIP_NUM_NETIF_CLIENT_DATA > 0
|
||||
static u8_t netif_client_id;
|
||||
#endif
|
||||
|
||||
#define NETIF_REPORT_TYPE_IPV4 0x01
|
||||
#define NETIF_REPORT_TYPE_IPV6 0x02
|
||||
static void netif_issue_reports(struct netif* netif, u8_t report_type);
|
||||
|
@ -162,7 +180,7 @@ netif_init(void)
|
|||
#endif /* NO_SYS */
|
||||
|
||||
#if LWIP_IPV6
|
||||
IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL));
|
||||
IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
|
||||
loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
@ -210,8 +228,13 @@ netif_input(struct pbuf *p, struct netif *inp)
|
|||
* These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET
|
||||
* to decide whether to forward to ethernet_input() or ip_input().
|
||||
* In other words, the functions only work when the netif
|
||||
* driver is implemented correctly!
|
||||
*
|
||||
* driver is implemented correctly!\n
|
||||
* Most members of struct netif should be be initialized by the
|
||||
* netif init function = netif driver (init parameter of this function).\n
|
||||
* IPv6: Don't forget to call netif_create_ip6_linklocal_address() after
|
||||
* setting the MAC address in struct netif.hwaddr
|
||||
* (IPv6 requires a link-local address).
|
||||
*
|
||||
* @return netif, or NULL if failed.
|
||||
*/
|
||||
struct netif *
|
||||
|
@ -236,20 +259,15 @@ netif_add(struct netif *netif,
|
|||
#if LWIP_IPV6
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
|
||||
netif->ip6_addr_state[0] = IP6_ADDR_INVALID;
|
||||
netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
|
||||
}
|
||||
netif->output_ip6 = netif_null_output_ip6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
|
||||
netif->flags = 0;
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
netif->dhcp = NULL;
|
||||
#endif /* LWIP_DHCP */
|
||||
#if LWIP_AUTOIP
|
||||
/* netif not under AutoIP control by default */
|
||||
netif->autoip = NULL;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#ifdef netif_get_client_data
|
||||
memset(netif->client_data, 0, sizeof(netif->client_data));
|
||||
#endif /* LWIP_NUM_NETIF_CLIENT_DATA */
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/* IPv6 address autoconfiguration not enabled by default */
|
||||
netif->ip6_autoconfig_enabled = 0;
|
||||
|
@ -257,10 +275,6 @@ netif_add(struct netif *netif,
|
|||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
|
||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||
#if LWIP_IPV6_DHCP6
|
||||
/* netif not under DHCPv6 control by default */
|
||||
netif->dhcp6 = NULL;
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
netif->status_callback = NULL;
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
|
@ -325,7 +339,7 @@ netif_add(struct netif *netif,
|
|||
|
||||
#if LWIP_IPV4
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip4
|
||||
* Change IP address configuration for a network interface (including netmask
|
||||
* and default gateway).
|
||||
*
|
||||
|
@ -362,6 +376,10 @@ netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *
|
|||
void
|
||||
netif_remove(struct netif *netif)
|
||||
{
|
||||
#if LWIP_IPV6
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -369,9 +387,14 @@ netif_remove(struct netif *netif)
|
|||
#if LWIP_IPV4
|
||||
if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
|
||||
#if LWIP_TCP
|
||||
tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), NULL);
|
||||
tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
|
||||
#endif /* LWIP_TCP */
|
||||
/* cannot do this for UDP, as there is no 'err' callback in udp pcbs */
|
||||
#if LWIP_UDP
|
||||
udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_RAW
|
||||
raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
|
||||
#endif /* LWIP_RAW */
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
|
@ -382,10 +405,25 @@ netif_remove(struct netif *netif)
|
|||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IPV4*/
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
#if LWIP_IPV6
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
|
||||
#if LWIP_TCP
|
||||
tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_UDP
|
||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_RAW
|
||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
||||
#endif /* LWIP_RAW */
|
||||
}
|
||||
}
|
||||
#if LWIP_IPV6_MLD
|
||||
/* stop MLD processing */
|
||||
mld6_stop(netif);
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (netif_is_up(netif)) {
|
||||
/* set netif down before removing (call callback function) */
|
||||
netif_set_down(netif);
|
||||
|
@ -440,7 +478,7 @@ netif_find(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
num = name[2] - '0';
|
||||
num = (u8_t)(name[2] - '0');
|
||||
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (num == netif->num &&
|
||||
|
@ -456,7 +494,7 @@ netif_find(const char *name)
|
|||
|
||||
#if LWIP_IPV4
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip4
|
||||
* Change the IP address of a network interface
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
|
@ -468,16 +506,22 @@ netif_find(const char *name)
|
|||
void
|
||||
netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
|
||||
{
|
||||
ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY);
|
||||
ip_addr_t new_addr;
|
||||
*ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4);
|
||||
IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
|
||||
|
||||
/* address is actually being changed? */
|
||||
if (ip4_addr_cmp(&new_addr, netif_ip4_addr(netif)) == 0) {
|
||||
if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
#if LWIP_TCP
|
||||
tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr);
|
||||
tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_UDP
|
||||
udp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr);
|
||||
udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_RAW
|
||||
raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
|
||||
#endif /* LWIP_RAW */
|
||||
|
||||
mib2_remove_ip4(netif);
|
||||
mib2_remove_route_ip4(0, netif);
|
||||
|
@ -501,7 +545,7 @@ netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip4
|
||||
* Change the default gateway for a network interface
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
|
@ -523,7 +567,7 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip4
|
||||
* Change the netmask of a network interface
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
|
@ -694,15 +738,11 @@ netif_set_link_up(struct netif *netif)
|
|||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
|
||||
#if LWIP_DHCP
|
||||
if (netif->dhcp) {
|
||||
dhcp_network_changed(netif);
|
||||
}
|
||||
dhcp_network_changed(netif);
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
if (netif->autoip) {
|
||||
autoip_network_changed(netif);
|
||||
}
|
||||
autoip_network_changed(netif);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
|
@ -761,7 +801,7 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
|
|||
err_t err;
|
||||
struct pbuf *last;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = 0;
|
||||
u16_t clen = 0;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
/* If we have a loopif, SNMP counters are adjusted for it,
|
||||
* if not they are adjusted for 'netif'. */
|
||||
|
@ -864,7 +904,6 @@ netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* ad
|
|||
void
|
||||
netif_poll(struct netif *netif)
|
||||
{
|
||||
struct pbuf *in;
|
||||
/* If we have a loopif, SNMP counters are adjusted for it,
|
||||
* if not they are adjusted for 'netif'. */
|
||||
#if MIB2_STATS
|
||||
|
@ -876,56 +915,52 @@ netif_poll(struct netif *netif)
|
|||
#endif /* MIB2_STATS */
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
do {
|
||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
in = netif->loop_first;
|
||||
if (in != NULL) {
|
||||
struct pbuf *in_end = in;
|
||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
while (netif->loop_first != NULL) {
|
||||
struct pbuf *in, *in_end;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = 1;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
while (in_end->len != in_end->tot_len) {
|
||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||
in_end = in_end->next;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
clen++;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
}
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
/* adjust the number of pbufs on queue */
|
||||
LWIP_ASSERT("netif->loop_cnt_current underflow",
|
||||
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
||||
netif->loop_cnt_current -= clen;
|
||||
u8_t clen = 1;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
|
||||
/* 'in_end' now points to the last pbuf from 'in' */
|
||||
if (in_end == netif->loop_last) {
|
||||
/* this was the last pbuf in the list */
|
||||
netif->loop_first = netif->loop_last = NULL;
|
||||
} else {
|
||||
/* pop the pbuf off the list */
|
||||
netif->loop_first = in_end->next;
|
||||
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
||||
}
|
||||
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
||||
in_end->next = NULL;
|
||||
in = in_end = netif->loop_first;
|
||||
while (in_end->len != in_end->tot_len) {
|
||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||
in_end = in_end->next;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
clen++;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
}
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
/* adjust the number of pbufs on queue */
|
||||
LWIP_ASSERT("netif->loop_cnt_current underflow",
|
||||
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
||||
netif->loop_cnt_current -= clen;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
|
||||
/* 'in_end' now points to the last pbuf from 'in' */
|
||||
if (in_end == netif->loop_last) {
|
||||
/* this was the last pbuf in the list */
|
||||
netif->loop_first = netif->loop_last = NULL;
|
||||
} else {
|
||||
/* pop the pbuf off the list */
|
||||
netif->loop_first = in_end->next;
|
||||
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
||||
}
|
||||
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
||||
in_end->next = NULL;
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
if (in != NULL) {
|
||||
LINK_STATS_INC(link.recv);
|
||||
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
|
||||
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
|
||||
/* loopback packets are always IP packets! */
|
||||
if (ip_input(in, netif) != ERR_OK) {
|
||||
pbuf_free(in);
|
||||
}
|
||||
/* Don't reference the packet any more! */
|
||||
in = NULL;
|
||||
LINK_STATS_INC(link.recv);
|
||||
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
|
||||
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
|
||||
/* loopback packets are always IP packets! */
|
||||
if (ip_input(in, netif) != ERR_OK) {
|
||||
pbuf_free(in);
|
||||
}
|
||||
/* go on while there is a packet on the list */
|
||||
} while (netif->loop_first != NULL);
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
}
|
||||
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
|
@ -946,15 +981,53 @@ netif_poll_all(void)
|
|||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_NUM_NETIF_CLIENT_DATA > 0
|
||||
/**
|
||||
* @ingroup netif_cd
|
||||
* Allocate an index to store data in client_data member of struct netif.
|
||||
* Returned value is an index in mentioned array.
|
||||
* @see LWIP_NUM_NETIF_CLIENT_DATA
|
||||
*/
|
||||
u8_t
|
||||
netif_alloc_client_data_id(void)
|
||||
{
|
||||
u8_t result = netif_client_id;
|
||||
netif_client_id++;
|
||||
|
||||
LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
|
||||
return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* @ingroup netif_ip6
|
||||
* Change an IPv6 address of a network interface
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
* @param addr_idx index of the IPv6 address
|
||||
* @param addr6 the new IPv6 address
|
||||
*
|
||||
* @note call netif_ip6_addr_set_state() to set the address valid/temptative
|
||||
*/
|
||||
void
|
||||
netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, ip6_addr_t *addr6)
|
||||
netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
|
||||
{
|
||||
LWIP_ASSERT("addr6 != NULL", addr6 != NULL);
|
||||
netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
|
||||
addr6->addr[2], addr6->addr[3]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
* @param addr_idx index of the IPv6 address
|
||||
* @param i0 word0 of the new IPv6 address
|
||||
* @param i1 word1 of the new IPv6 address
|
||||
* @param i2 word2 of the new IPv6 address
|
||||
* @param i3 word3 of the new IPv6 address
|
||||
*/
|
||||
void
|
||||
netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
|
||||
{
|
||||
|
@ -968,7 +1041,21 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1,
|
|||
(old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
|
||||
|
||||
/* @todo: tcp_netif_ipv6_addr_changed()/udp_netif_ipv6_addr_changed() */
|
||||
if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
|
||||
#if LWIP_TCP || LWIP_UDP
|
||||
ip_addr_t new_ipaddr;
|
||||
IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
|
||||
#endif /* LWIP_TCP || LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_UDP
|
||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_RAW
|
||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
||||
#endif /* LWIP_RAW */
|
||||
}
|
||||
/* @todo: remove/readd mib2 ip6 entries? */
|
||||
|
||||
IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3);
|
||||
|
@ -985,6 +1072,16 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1,
|
|||
netif_ip6_addr_state(netif, addr_idx)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup netif_ip6
|
||||
* Change the state of an IPv6 address of a network interface
|
||||
* (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE
|
||||
* includes the number of checks done, see ip6_addr.h)
|
||||
*
|
||||
* @param netif the network interface to change
|
||||
* @param addr_idx index of the IPv6 address
|
||||
* @param state the new IPv6 address state
|
||||
*/
|
||||
void
|
||||
netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
|
||||
{
|
||||
|
@ -999,9 +1096,24 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
|
|||
u8_t new_valid = state & IP6_ADDR_VALID;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
|
||||
|
||||
#if LWIP_IPV6_MLD
|
||||
/* Reevaluate solicited-node multicast group membership. */
|
||||
if (netif->flags & NETIF_FLAG_MLD6) {
|
||||
nd6_adjust_mld_membership(netif, addr_idx, state);
|
||||
}
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
|
||||
if (old_valid && !new_valid) {
|
||||
/* address about to be removed by setting invalid */
|
||||
/* @todo: tcp_netif_ipv6_addr_changed()/udp_netif_ipv6_addr_changed() */
|
||||
#if LWIP_TCP
|
||||
tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_UDP
|
||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_RAW
|
||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
||||
#endif /* LWIP_RAW */
|
||||
/* @todo: remove mib2 ip6 entries? */
|
||||
}
|
||||
netif->ip6_addr_state[addr_idx] = state;
|
||||
|
@ -1046,7 +1158,7 @@ netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip6
|
||||
* Create a link-local IPv6 address on a netif (stored in slot 0)
|
||||
*
|
||||
* @param netif the netif to create the address on
|
||||
|
@ -1065,11 +1177,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
|
|||
/* Generate interface ID. */
|
||||
if (from_mac_48bit) {
|
||||
/* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
|
||||
ip_2_ip6(&netif->ip6_addr[0])->addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
|
||||
ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
|
||||
((u32_t)(netif->hwaddr[1]) << 16) |
|
||||
((u32_t)(netif->hwaddr[2]) << 8) |
|
||||
(0xff));
|
||||
ip_2_ip6(&netif->ip6_addr[0])->addr[3] = htonl((0xfeul << 24) |
|
||||
ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) |
|
||||
((u32_t)(netif->hwaddr[3]) << 16) |
|
||||
((u32_t)(netif->hwaddr[4]) << 8) |
|
||||
(netif->hwaddr[5]));
|
||||
|
@ -1090,15 +1202,15 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
|
|||
/* Set address state. */
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||
/* Will perform duplicate address detection (DAD). */
|
||||
netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
|
||||
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
|
||||
#else
|
||||
/* Consider address valid. */
|
||||
netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
|
||||
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup netif
|
||||
* @ingroup netif_ip6
|
||||
* This function allows for the easy addition of a new IPv6 address to an interface.
|
||||
* It takes care of finding an empty slot and then sets the address tentative
|
||||
* (to make sure that all the subsequent processing happens).
|
||||
|
@ -1123,7 +1235,7 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos
|
|||
|
||||
/* Find a free slot -- musn't be the first one (reserved for link local) */
|
||||
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
|
||||
if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
|
||||
ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
|
||||
netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
|
||||
if (chosen_idx != NULL) {
|
||||
|
|
|
@ -32,6 +32,49 @@
|
|||
*
|
||||
* Therefore, looping through a pbuf of a single packet, has an
|
||||
* loop end condition (tot_len == p->len), NOT (next == NULL).
|
||||
*
|
||||
* Example of custom pbuf usage for zero-copy RX:
|
||||
@code{.c}
|
||||
typedef struct my_custom_pbuf
|
||||
{
|
||||
struct pbuf_custom p;
|
||||
void* dma_descriptor;
|
||||
} my_custom_pbuf_t;
|
||||
|
||||
LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool");
|
||||
|
||||
void my_pbuf_free_custom(void* p)
|
||||
{
|
||||
my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p;
|
||||
|
||||
LOCK_INTERRUPTS();
|
||||
free_rx_dma_descriptor(my_pbuf->dma_descriptor);
|
||||
LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf);
|
||||
UNLOCK_INTERRUPTS();
|
||||
}
|
||||
|
||||
void eth_rx_irq()
|
||||
{
|
||||
dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet();
|
||||
my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL);
|
||||
|
||||
my_pbuf->p.custom_free_function = my_pbuf_free_custom;
|
||||
my_pbuf->dma_descriptor = dma_desc;
|
||||
|
||||
invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length);
|
||||
|
||||
struct pbuf* p = pbuf_alloced_custom(PBUF_RAW,
|
||||
dma_desc->rx_length,
|
||||
PBUF_REF,
|
||||
&my_pbuf->p,
|
||||
dma_desc->rx_data,
|
||||
dma_desc->max_buffer_size);
|
||||
|
||||
if(netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -525,11 +568,11 @@ pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
|
|||
}
|
||||
|
||||
if (header_size_increment < 0) {
|
||||
increment_magnitude = -header_size_increment;
|
||||
increment_magnitude = (u16_t)-header_size_increment;
|
||||
/* Check that we aren't going to move off the end of the pbuf */
|
||||
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
|
||||
} else {
|
||||
increment_magnitude = header_size_increment;
|
||||
increment_magnitude = (u16_t)header_size_increment;
|
||||
#if 0
|
||||
/* Can't assert these as some callers speculatively call
|
||||
pbuf_header() to see if it's OK. Will return 1 below instead. */
|
||||
|
@ -743,10 +786,10 @@ pbuf_free(struct pbuf *p)
|
|||
* @param p first pbuf of chain
|
||||
* @return the number of pbufs in a chain
|
||||
*/
|
||||
u8_t
|
||||
pbuf_clen(struct pbuf *p)
|
||||
u16_t
|
||||
pbuf_clen(const struct pbuf *p)
|
||||
{
|
||||
u8_t len;
|
||||
u16_t len;
|
||||
|
||||
len = 0;
|
||||
while (p != NULL) {
|
||||
|
@ -766,12 +809,9 @@ pbuf_clen(struct pbuf *p)
|
|||
void
|
||||
pbuf_ref(struct pbuf *p)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
/* pbuf given? */
|
||||
if (p != NULL) {
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
++(p->ref);
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
SYS_ARCH_INC(p->ref, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,12 +934,12 @@ pbuf_dechain(struct pbuf *p)
|
|||
* enough to hold p_from
|
||||
*/
|
||||
err_t
|
||||
pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
|
||||
{
|
||||
u16_t offset_to=0, offset_from=0, len;
|
||||
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
|
||||
(void*)p_to, (void*)p_from));
|
||||
(const void*)p_to, (const void*)p_from));
|
||||
|
||||
/* is the target big enough to hold the source? */
|
||||
LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
|
||||
|
@ -961,9 +1001,9 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
|||
* @return the number of bytes copied, or 0 on failure
|
||||
*/
|
||||
u16_t
|
||||
pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
{
|
||||
struct pbuf *p;
|
||||
const struct pbuf *p;
|
||||
u16_t left;
|
||||
u16_t buf_copy_len;
|
||||
u16_t copied_total = 0;
|
||||
|
@ -985,8 +1025,9 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||
} else {
|
||||
/* copy from this buffer. maybe only partially. */
|
||||
buf_copy_len = p->len - offset;
|
||||
if (buf_copy_len > len)
|
||||
buf_copy_len = len;
|
||||
if (buf_copy_len > len) {
|
||||
buf_copy_len = len;
|
||||
}
|
||||
/* copy the necessary parts of the buffer */
|
||||
MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
|
||||
copied_total += buf_copy_len;
|
||||
|
@ -1048,6 +1089,24 @@ void pbuf_split_64k(struct pbuf *p, struct pbuf **rest)
|
|||
}
|
||||
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
|
||||
|
||||
/* Actual implementation of pbuf_skip() but returning const pointer... */
|
||||
static const struct pbuf*
|
||||
pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset)
|
||||
{
|
||||
u16_t offset_left = in_offset;
|
||||
const struct pbuf* q = in;
|
||||
|
||||
/* get the correct pbuf */
|
||||
while ((q != NULL) && (q->len <= offset_left)) {
|
||||
offset_left -= q->len;
|
||||
q = q->next;
|
||||
}
|
||||
if (out_offset != NULL) {
|
||||
*out_offset = offset_left;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup pbuf
|
||||
* Skip a number of bytes at the start of a pbuf
|
||||
|
@ -1060,18 +1119,8 @@ void pbuf_split_64k(struct pbuf *p, struct pbuf **rest)
|
|||
struct pbuf*
|
||||
pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
|
||||
{
|
||||
u16_t offset_left = in_offset;
|
||||
struct pbuf* q = in;
|
||||
|
||||
/* get the correct pbuf */
|
||||
while ((q != NULL) && (q->len <= offset_left)) {
|
||||
offset_left -= q->len;
|
||||
q = q->next;
|
||||
}
|
||||
if (out_offset != NULL) {
|
||||
*out_offset = offset_left;
|
||||
}
|
||||
return q;
|
||||
const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset);
|
||||
return LWIP_CONST_CAST(struct pbuf*, out);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1179,7 +1228,7 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
|||
return p;
|
||||
}
|
||||
err = pbuf_copy(q, p);
|
||||
LWIP_UNUSED_ARG(err);
|
||||
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
|
||||
pbuf_free(p);
|
||||
return q;
|
||||
|
@ -1226,7 +1275,7 @@ pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
|||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/**
|
||||
/**
|
||||
* @ingroup pbuf
|
||||
* Get one byte from the specified position in a pbuf
|
||||
* WARNING: returns zero for offset >= p->tot_len
|
||||
|
@ -1236,16 +1285,34 @@ pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
|||
* @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
|
||||
*/
|
||||
u8_t
|
||||
pbuf_get_at(struct pbuf* p, u16_t offset)
|
||||
pbuf_get_at(const struct pbuf* p, u16_t offset)
|
||||
{
|
||||
int ret = pbuf_try_get_at(p, offset);
|
||||
if (ret >= 0) {
|
||||
return (u8_t)ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup pbuf
|
||||
* Get one byte from the specified position in a pbuf
|
||||
*
|
||||
* @param p pbuf to parse
|
||||
* @param offset offset into p of the byte to return
|
||||
* @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len
|
||||
*/
|
||||
int
|
||||
pbuf_try_get_at(const struct pbuf* p, u16_t offset)
|
||||
{
|
||||
u16_t q_idx;
|
||||
struct pbuf* q = pbuf_skip(p, offset, &q_idx);
|
||||
const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx);
|
||||
|
||||
/* return requested data if pbuf is OK */
|
||||
if ((q != NULL) && (q->len > q_idx)) {
|
||||
return ((u8_t*)q->payload)[q_idx];
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1281,29 +1348,33 @@ pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data)
|
|||
* (0xffff if p is too short, diffoffset+1 otherwise)
|
||||
*/
|
||||
u16_t
|
||||
pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
|
||||
pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n)
|
||||
{
|
||||
u16_t start = offset;
|
||||
struct pbuf* q = p;
|
||||
|
||||
/* get the correct pbuf */
|
||||
const struct pbuf* q = p;
|
||||
u16_t i;
|
||||
|
||||
/* pbuf long enough to perform check? */
|
||||
if(p->tot_len < (offset + n)) {
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
/* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */
|
||||
while ((q != NULL) && (q->len <= start)) {
|
||||
start -= q->len;
|
||||
q = q->next;
|
||||
}
|
||||
|
||||
/* return requested data if pbuf is OK */
|
||||
if ((q != NULL) && (q->len > start)) {
|
||||
u16_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
u8_t a = pbuf_get_at(q, start + i);
|
||||
u8_t b = ((const u8_t*)s2)[i];
|
||||
if (a != b) {
|
||||
return i+1;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
/* We know pbuf_get_at() succeeds because of p->tot_len check above. */
|
||||
u8_t a = pbuf_get_at(q, start + i);
|
||||
u8_t b = ((const u8_t*)s2)[i];
|
||||
if (a != b) {
|
||||
return i+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0xffff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1319,7 +1390,7 @@ pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
|
|||
* @return 0xFFFF if substr was not found in p or the index where it was found
|
||||
*/
|
||||
u16_t
|
||||
pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
|
||||
pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
|
||||
{
|
||||
u16_t i;
|
||||
u16_t max = p->tot_len - mem_len;
|
||||
|
@ -1346,7 +1417,7 @@ pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
|
|||
* @return 0xFFFF if substr was not found in p or the index where it was found
|
||||
*/
|
||||
u16_t
|
||||
pbuf_strstr(struct pbuf* p, const char* substr)
|
||||
pbuf_strstr(const struct pbuf* p, const char* substr)
|
||||
{
|
||||
size_t substr_len;
|
||||
if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
* different types of protocols besides (or overriding) those
|
||||
* already available in lwIP.\n
|
||||
* See also @ref raw_raw
|
||||
*
|
||||
* @defgroup raw_raw RAW
|
||||
* @ingroup callbackstyle_api
|
||||
* Implementation of raw protocol PCBs for low-level handling of
|
||||
* different types of protocols besides (or overriding) those
|
||||
* already available in lwIP.\n
|
||||
* @see @ref raw_api
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -38,21 +45,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup raw_api RAW API
|
||||
* @ingroup callbackstyle_api
|
||||
* @verbinclude "rawapi.txt"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup raw_raw RAW
|
||||
* @ingroup raw_api
|
||||
* Implementation of raw protocol PCBs for low-level handling of
|
||||
* different types of protocols besides (or overriding) those
|
||||
* already available in lwIP.\n
|
||||
* @see @ref raw_api
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
||||
|
@ -88,7 +80,7 @@ raw_input_match(struct raw_pcb *pcb, u8_t broadcast)
|
|||
return 1;
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -111,7 +103,7 @@ raw_input_match(struct raw_pcb *pcb, u8_t broadcast)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -204,7 +196,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||
* 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
|
||||
* @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
|
@ -217,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||
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)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
|
||||
|
@ -241,7 +233,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
|||
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)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
|
||||
|
@ -258,9 +250,6 @@ raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
|||
* 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)
|
||||
|
@ -291,7 +280,6 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|||
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;
|
||||
|
@ -332,10 +320,16 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|||
}
|
||||
}
|
||||
|
||||
netif = ip_route(&pcb->local_ip, dst_ip);
|
||||
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
||||
/* Don't call ip_route() with IP_ANY_TYPE */
|
||||
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
|
||||
} else {
|
||||
netif = ip_route(&pcb->local_ip, ipaddr);
|
||||
}
|
||||
|
||||
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);
|
||||
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
|
@ -360,7 +354,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|||
|
||||
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);
|
||||
src_ip = ip_netif_get_local_ip(netif, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (src_ip == NULL) {
|
||||
if (q != p) {
|
||||
|
@ -377,15 +371,15 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|||
#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));
|
||||
if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) {
|
||||
u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr));
|
||||
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);
|
||||
err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
/* did we chain a header earlier? */
|
||||
|
@ -479,7 +473,9 @@ raw_new(u8_t proto)
|
|||
* @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 type IP address type, see @ref lwip_ip_addr_type definitions.
|
||||
* If you want to listen to IPv4 and IPv6 (dual-stack) packets,
|
||||
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
|
||||
* @param proto the protocol number (next header) of the IPv6 packet payload
|
||||
* (e.g. IP6_NEXTH_ICMP6)
|
||||
*
|
||||
|
@ -501,4 +497,25 @@ raw_new_ip_type(u8_t type, u8_t proto)
|
|||
return pcb;
|
||||
}
|
||||
|
||||
/** This function is called from netif.c when address is changed
|
||||
*
|
||||
* @param old_addr IP address of the netif before change
|
||||
* @param new_addr IP address of the netif after change
|
||||
*/
|
||||
void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr)
|
||||
{
|
||||
struct raw_pcb* rpcb;
|
||||
|
||||
if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) {
|
||||
for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&rpcb->local_ip, old_addr)) {
|
||||
/* The PCB is bound to the old ipaddr and
|
||||
* is set to bound to the new one instead */
|
||||
ip_addr_copy(rpcb->local_ip, *new_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LWIP_RAW */
|
||||
|
|
|
@ -36,6 +36,44 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_layer Porting (system abstraction layer)
|
||||
* @ingroup lwip
|
||||
* @verbinclude "sys_arch.txt"
|
||||
*
|
||||
* @defgroup sys_os OS abstraction layer
|
||||
* @ingroup sys_layer
|
||||
* No need to implement functions in this section in NO_SYS mode.
|
||||
*
|
||||
* @defgroup sys_sem Semaphores
|
||||
* @ingroup sys_os
|
||||
*
|
||||
* @defgroup sys_mutex Mutexes
|
||||
* @ingroup sys_os
|
||||
* Mutexes are recommended to correctly handle priority inversion,
|
||||
* especially if you use LWIP_CORE_LOCKING .
|
||||
*
|
||||
* @defgroup sys_mbox Mailboxes
|
||||
* @ingroup sys_os
|
||||
*
|
||||
* @defgroup sys_time Time
|
||||
* @ingroup sys_layer
|
||||
*
|
||||
* @defgroup sys_prot Critical sections
|
||||
* @ingroup sys_layer
|
||||
* Used to protect short regions of code against concurrent access.
|
||||
* - Your system is a bare-metal system (probably with an RTOS)
|
||||
* and interrupts are under your control:
|
||||
* Implement this as LockInterrupts() / UnlockInterrupts()
|
||||
* - Your system uses an RTOS with deferred interrupt handling from a
|
||||
* worker thread: Implement as a global mutex or lock/unlock scheduler
|
||||
* - Your system uses a high-level OS with e.g. POSIX signals:
|
||||
* Implement as a global mutex
|
||||
*
|
||||
* @defgroup sys_misc Misc
|
||||
* @ingroup sys_os
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
* @file
|
||||
* Transmission Control Protocol for IP
|
||||
* See also @ref tcp_raw
|
||||
*
|
||||
* @defgroup tcp_raw TCP
|
||||
* @ingroup callbackstyle_api
|
||||
* Transmission Control Protocol for IP\n
|
||||
* @see @ref raw_api and @ref netconn
|
||||
*
|
||||
* Common functions for the TCP implementation, such as functinos
|
||||
* for manipulating the data structures and the TCP timer functions. TCP functions
|
||||
* related to input and output is found in tcp_in.c and tcp_out.c respectively.\n
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -36,17 +45,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tcp_raw TCP
|
||||
* @ingroup raw_api
|
||||
* Transmission Control Protocol for IP\n
|
||||
* @see @ref raw_api and @ref netconn
|
||||
*
|
||||
* Common functions for the TCP implementation, such as functinos
|
||||
* for manipulating the data structures and the TCP timer functions. TCP functions
|
||||
* related to input and output is found in tcp_in.c and tcp_out.c respectively.\n
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||
|
@ -87,7 +85,7 @@
|
|||
#define INITIAL_MSS TCP_MSS
|
||||
#endif
|
||||
|
||||
const char * const tcp_state_str[] = {
|
||||
static const char * const tcp_state_str[] = {
|
||||
"CLOSED",
|
||||
"LISTEN",
|
||||
"SYN_SENT",
|
||||
|
@ -106,10 +104,10 @@ static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START;
|
|||
|
||||
/* Incremented every coarse grained timer shot (typically every 500 ms). */
|
||||
u32_t tcp_ticks;
|
||||
const u8_t tcp_backoff[13] =
|
||||
static const u8_t tcp_backoff[13] =
|
||||
{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
|
||||
/* Times per slowtmr hits */
|
||||
const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
|
||||
static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
|
||||
|
||||
/* The TCP PCB lists. */
|
||||
|
||||
|
@ -531,7 +529,7 @@ tcp_abort(struct tcp_pcb *pcb)
|
|||
*
|
||||
* @param pcb the tcp_pcb to bind (no check is done whether this pcb is
|
||||
* already bound!)
|
||||
* @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind
|
||||
* @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind
|
||||
* to any local address
|
||||
* @param port the local port to bind to
|
||||
* @return ERR_USE if the port is already in use
|
||||
|
@ -548,12 +546,12 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|||
#if LWIP_IPV4
|
||||
/* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
|
||||
if (ipaddr == NULL) {
|
||||
ipaddr = IP_ADDR_ANY;
|
||||
ipaddr = IP4_ADDR_ANY;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
/* still need to check for ipaddr == NULL in IPv6 only case */
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
@ -638,19 +636,44 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
*
|
||||
* @note The original tcp_pcb is freed. This function therefore has to be
|
||||
* called like this:
|
||||
* tpcb = tcp_listen(tpcb);
|
||||
* tpcb = tcp_listen_with_backlog(tpcb, backlog);
|
||||
*/
|
||||
struct tcp_pcb *
|
||||
tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
return tcp_listen_with_backlog_and_err(pcb, backlog, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup tcp_raw
|
||||
* Set the state of the connection to be LISTEN, which means that it
|
||||
* is able to accept incoming connections. The protocol control block
|
||||
* is reallocated in order to consume less memory. Setting the
|
||||
* connection to LISTEN is an irreversible process.
|
||||
*
|
||||
* @param pcb the original tcp_pcb
|
||||
* @param backlog the incoming connections queue limit
|
||||
* @param err when NULL is returned, this contains the error reason
|
||||
* @return tcp_pcb used for listening, consumes less memory.
|
||||
*
|
||||
* @note The original tcp_pcb is freed. This function therefore has to be
|
||||
* called like this:
|
||||
* tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err);
|
||||
*/
|
||||
struct tcp_pcb *
|
||||
tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb = NULL;
|
||||
err_t res;
|
||||
|
||||
LWIP_UNUSED_ARG(backlog);
|
||||
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
|
||||
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done);
|
||||
|
||||
/* already listening? */
|
||||
if (pcb->state == LISTEN) {
|
||||
return pcb;
|
||||
lpcb = (struct tcp_pcb_listen*)pcb;
|
||||
res = ERR_ALREADY;
|
||||
goto done;
|
||||
}
|
||||
#if SO_REUSE
|
||||
if (ip_get_option(pcb, SOF_REUSEADDR)) {
|
||||
|
@ -661,14 +684,17 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
||||
/* this address/port is already used */
|
||||
return NULL;
|
||||
lpcb = NULL;
|
||||
res = ERR_USE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
|
||||
if (lpcb == NULL) {
|
||||
return NULL;
|
||||
res = ERR_MEM;
|
||||
goto done;
|
||||
}
|
||||
lpcb->callback_arg = pcb->callback_arg;
|
||||
lpcb->local_port = pcb->local_port;
|
||||
|
@ -690,9 +716,14 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||
#endif /* LWIP_CALLBACK_API */
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
lpcb->accepts_pending = 0;
|
||||
lpcb->backlog = backlog;
|
||||
tcp_backlog_set(lpcb, backlog);
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
|
||||
res = ERR_OK;
|
||||
done:
|
||||
if (err != NULL) {
|
||||
*err = res;
|
||||
}
|
||||
return (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
|
||||
|
@ -828,7 +859,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
|||
u32_t iss;
|
||||
u16_t old_local_port;
|
||||
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
@ -882,10 +913,11 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
|||
#endif /* SO_REUSE */
|
||||
}
|
||||
|
||||
iss = tcp_next_iss();
|
||||
iss = tcp_next_iss(pcb);
|
||||
pcb->rcv_nxt = 0;
|
||||
pcb->snd_nxt = iss;
|
||||
pcb->lastack = iss - 1;
|
||||
pcb->snd_wl2 = iss - 1;
|
||||
pcb->snd_lbb = iss - 1;
|
||||
/* Start with a window that does not need scaling. When window scaling is
|
||||
enabled and used, the window is enlarged when both sides agree on scaling. */
|
||||
|
@ -1096,7 +1128,9 @@ tcp_slowtmr_start:
|
|||
/* If the PCB should be removed, do it. */
|
||||
if (pcb_remove) {
|
||||
struct tcp_pcb *pcb2;
|
||||
tcp_err_fn err_fn;
|
||||
#if LWIP_CALLBACK_API
|
||||
tcp_err_fn err_fn = pcb->errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
void *err_arg;
|
||||
tcp_pcb_purge(pcb);
|
||||
/* Remove PCB from tcp_active_pcbs list. */
|
||||
|
@ -1114,7 +1148,6 @@ tcp_slowtmr_start:
|
|||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
|
||||
err_fn = pcb->errf;
|
||||
err_arg = pcb->callback_arg;
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
|
@ -1492,7 +1525,6 @@ struct tcp_pcb *
|
|||
tcp_alloc(u8_t prio)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
u32_t iss;
|
||||
|
||||
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
|
||||
if (pcb == NULL) {
|
||||
|
@ -1555,11 +1587,6 @@ tcp_alloc(u8_t prio)
|
|||
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
||||
pcb->rtime = -1;
|
||||
pcb->cwnd = 1;
|
||||
iss = tcp_next_iss();
|
||||
pcb->snd_wl2 = iss;
|
||||
pcb->snd_nxt = iss;
|
||||
pcb->lastack = iss;
|
||||
pcb->snd_lbb = iss;
|
||||
pcb->tmr = tcp_ticks;
|
||||
pcb->last_timer = tcp_timer_ctr;
|
||||
|
||||
|
@ -1603,7 +1630,9 @@ tcp_new(void)
|
|||
* place it on any of the TCP PCB lists.
|
||||
* The pcb is not put on any list until binding using tcp_bind().
|
||||
*
|
||||
* @param type IP address type, see IPADDR_TYPE_XX definitions.
|
||||
* @param type IP address type, see @ref lwip_ip_addr_type definitions.
|
||||
* If you want to listen to IPv4 and IPv6 (dual-stack) connections,
|
||||
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
|
||||
* @return a new tcp_pcb that initially is in state CLOSED
|
||||
*/
|
||||
struct tcp_pcb *
|
||||
|
@ -1680,6 +1709,8 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
|
|||
* Used to specify the function that should be called when a fatal error
|
||||
* has occurred on the connection.
|
||||
*
|
||||
* @note The corresponding pcb is already freed when this callback is called!
|
||||
*
|
||||
* @param pcb tcp_pcb to set the err callback
|
||||
* @param err callback function to call for this pcb when a fatal error
|
||||
* has occurred on the connection
|
||||
|
@ -1823,12 +1854,18 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
|||
* @return u32_t pseudo random sequence number
|
||||
*/
|
||||
u32_t
|
||||
tcp_next_iss(void)
|
||||
tcp_next_iss(struct tcp_pcb *pcb)
|
||||
{
|
||||
#ifdef LWIP_HOOK_TCP_ISN
|
||||
return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port);
|
||||
#else /* LWIP_HOOK_TCP_ISN */
|
||||
static u32_t iss = 6510;
|
||||
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
|
||||
iss += tcp_ticks; /* XXX */
|
||||
return iss;
|
||||
#endif /* LWIP_HOOK_TCP_ISN */
|
||||
}
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
|
@ -1897,19 +1934,18 @@ tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest
|
|||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
#if LWIP_IPV4
|
||||
/** Helper function for tcp_netif_ipv4_addr_changed() that iterates a pcb list */
|
||||
/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */
|
||||
static void
|
||||
tcp_netif_ipv4_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list)
|
||||
tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
pcb = pcb_list;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (IP_IS_V4_VAL(pcb->local_ip) && ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr)
|
||||
if (ip_addr_cmp(&pcb->local_ip, old_addr)
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||
&& !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))
|
||||
&& (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
) {
|
||||
/* this connection must be aborted */
|
||||
|
@ -1925,35 +1961,32 @@ tcp_netif_ipv4_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb*
|
|||
|
||||
/** This function is called from netif.c when address is changed or netif is removed
|
||||
*
|
||||
* @param old_addr IPv4 address of the netif before change
|
||||
* @param new_addr IPv4 address of the netif after change or NULL if netif has been removed
|
||||
* @param old_addr IP address of the netif before change
|
||||
* @param new_addr IP address of the netif after change or NULL if netif has been removed
|
||||
*/
|
||||
void
|
||||
tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr)
|
||||
tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb, *next;
|
||||
|
||||
tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_active_pcbs);
|
||||
tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_bound_pcbs);
|
||||
if (!ip_addr_isany(old_addr)) {
|
||||
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs);
|
||||
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs);
|
||||
|
||||
if (!ip4_addr_isany(new_addr)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
|
||||
next = lpcb->next;
|
||||
/* Is this an IPv4 pcb? */
|
||||
if (IP_IS_V4_VAL(lpcb->local_ip)) {
|
||||
if (!ip_addr_isany(new_addr)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
|
||||
next = lpcb->next;
|
||||
/* PCB bound to current local interface address? */
|
||||
if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) &&
|
||||
(ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) {
|
||||
if (ip_addr_cmp(&lpcb->local_ip, old_addr)) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr);
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_copy(lpcb->local_ip, *new_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
const char*
|
||||
tcp_debug_state_str(enum tcp_state s)
|
||||
|
@ -1973,13 +2006,13 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
|
||||
lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
|
||||
ntohl(tcphdr->seqno)));
|
||||
lwip_ntohl(tcphdr->seqno)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
|
||||
ntohl(tcphdr->ackno)));
|
||||
lwip_ntohl(tcphdr->ackno)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
|
||||
TCPH_HDRLEN(tcphdr),
|
||||
|
@ -1989,12 +2022,12 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||
(u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1),
|
||||
(u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1),
|
||||
(u16_t)(TCPH_FLAGS(tcphdr) & 1),
|
||||
ntohs(tcphdr->wnd)));
|
||||
lwip_ntohs(tcphdr->wnd)));
|
||||
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
|
||||
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
|
||||
lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include "lwip/stats.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
#include "lwip/nd6.h"
|
||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||
|
@ -199,7 +198,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
/* remember the pointer to the second part of the options */
|
||||
tcphdr_opt2 = (u8_t*)p->next->payload;
|
||||
|
||||
|
||||
/* advance p->next to point after the options, and manually
|
||||
adjust p->tot_len to keep it consistent with the changed p->next */
|
||||
pbuf_header(p->next, -(s16_t)opt2len);
|
||||
|
@ -210,11 +209,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
|
||||
/* Convert fields in TCP header to host byte order. */
|
||||
tcphdr->src = ntohs(tcphdr->src);
|
||||
tcphdr->dest = ntohs(tcphdr->dest);
|
||||
seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
|
||||
ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
|
||||
tcphdr->wnd = ntohs(tcphdr->wnd);
|
||||
tcphdr->src = lwip_ntohs(tcphdr->src);
|
||||
tcphdr->dest = lwip_ntohs(tcphdr->dest);
|
||||
seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno);
|
||||
ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno);
|
||||
tcphdr->wnd = lwip_ntohs(tcphdr->wnd);
|
||||
|
||||
flags = TCPH_FLAGS(tcphdr);
|
||||
tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
|
||||
|
@ -359,6 +358,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||
((pcb->refused_data != NULL) && (tcplen > 0))) {
|
||||
/* pcb has been aborted or refused data is still refused and the new
|
||||
segment contains data */
|
||||
if (pcb->rcv_ann_wnd == 0) {
|
||||
/* this is a zero-window probe, we respond to it with current RCV.NXT
|
||||
and drop the data segment */
|
||||
tcp_send_empty_ack(pcb);
|
||||
}
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
MIB2_STATS_INC(mib2.tcpinerrs);
|
||||
goto aborted;
|
||||
|
@ -535,10 +539,7 @@ dropped:
|
|||
* connection (from tcp_input()).
|
||||
*
|
||||
* @param pcb the tcp_pcb_listen for which a segment arrived
|
||||
* @return ERR_OK if the segment was processed
|
||||
* another err_t on error
|
||||
*
|
||||
* @note the return value is not (yet?) used in tcp_input()
|
||||
* @note the segment which arrived is saved in global variables, therefore only the pcb
|
||||
* involved is passed as a parameter to this function
|
||||
*/
|
||||
|
@ -546,6 +547,7 @@ static void
|
|||
tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
{
|
||||
struct tcp_pcb *npcb;
|
||||
u32_t iss;
|
||||
err_t rc;
|
||||
|
||||
if (flags & TCP_RST) {
|
||||
|
@ -593,6 +595,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||
npcb->state = SYN_RCVD;
|
||||
npcb->rcv_nxt = seqno + 1;
|
||||
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
|
||||
iss = tcp_next_iss(npcb);
|
||||
npcb->snd_wl2 = iss;
|
||||
npcb->snd_nxt = iss;
|
||||
npcb->lastack = iss;
|
||||
npcb->snd_lbb = iss;
|
||||
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
|
||||
npcb->callback_arg = pcb->callback_arg;
|
||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||
|
@ -606,7 +613,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||
|
||||
/* Parse any options in the SYN. */
|
||||
tcp_parseopt(npcb);
|
||||
npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd);
|
||||
npcb->snd_wnd = tcphdr->wnd;
|
||||
npcb->snd_wnd_max = npcb->snd_wnd;
|
||||
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
|
||||
|
||||
|
@ -748,14 +755,14 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
switch (pcb->state) {
|
||||
case SYN_SENT:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
|
||||
pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
/* received SYN ACK with expected sequence number? */
|
||||
if ((flags & TCP_ACK) && (flags & TCP_SYN)
|
||||
&& (ackno == pcb->lastack + 1)) {
|
||||
pcb->rcv_nxt = seqno + 1;
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
||||
pcb->lastack = ackno;
|
||||
pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
|
||||
pcb->snd_wnd = tcphdr->wnd;
|
||||
pcb->snd_wnd_max = pcb->snd_wnd;
|
||||
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
|
||||
pcb->state = ESTABLISHED;
|
||||
|
@ -887,7 +894,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
case FIN_WAIT_1:
|
||||
tcp_receive(pcb);
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
|
||||
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
|
||||
pcb->unsent == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
|
@ -899,7 +907,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
tcp_ack_now(pcb);
|
||||
pcb->state = CLOSING;
|
||||
}
|
||||
} else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
|
||||
} else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
|
||||
pcb->unsent == NULL) {
|
||||
pcb->state = FIN_WAIT_2;
|
||||
}
|
||||
break;
|
||||
|
@ -916,7 +925,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
break;
|
||||
case CLOSING:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV_ACTIVE(pcb);
|
||||
|
@ -926,7 +935,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
break;
|
||||
case LAST_ACK:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
|
||||
recv_flags |= TF_CLOSED;
|
||||
|
@ -997,7 +1006,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
#if TCP_QUEUE_OOSEQ
|
||||
struct tcp_seg *prev, *cseg;
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
struct pbuf *p;
|
||||
s32_t off;
|
||||
s16_t m;
|
||||
u32_t right_wnd_edge;
|
||||
|
@ -1140,18 +1148,18 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
|
||||
ackno,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno): 0,
|
||||
lwip_ntohl(pcb->unacked->tcphdr->seqno): 0,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
|
||||
lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
|
||||
|
||||
/* Remove segment from the unacknowledged list if the incoming
|
||||
ACK acknowledges them. */
|
||||
while (pcb->unacked != NULL &&
|
||||
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked), ackno)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
|
||||
ntohl(pcb->unacked->tcphdr->seqno),
|
||||
ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
lwip_ntohl(pcb->unacked->tcphdr->seqno),
|
||||
lwip_ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked)));
|
||||
|
||||
next = pcb->unacked;
|
||||
|
@ -1199,10 +1207,10 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
->unsent list after a retransmission, so these segments may
|
||||
in fact have been sent once. */
|
||||
while (pcb->unsent != NULL &&
|
||||
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
|
||||
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent)));
|
||||
|
||||
next = pcb->unsent;
|
||||
|
@ -1314,8 +1322,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
adjust the ->data pointer in the seg and the segment
|
||||
length.*/
|
||||
|
||||
struct pbuf *p = inseg.p;
|
||||
off = pcb->rcv_nxt - seqno;
|
||||
p = inseg.p;
|
||||
LWIP_ASSERT("inseg.p != NULL", inseg.p);
|
||||
LWIP_ASSERT("insane offset!", (off < 0x7fff));
|
||||
if (inseg.p->len < off) {
|
||||
|
@ -1779,12 +1787,12 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
|||
tsval |= (tcp_getoptbyte() << 16);
|
||||
tsval |= (tcp_getoptbyte() << 24);
|
||||
if (flags & TCP_SYN) {
|
||||
pcb->ts_recent = ntohl(tsval);
|
||||
pcb->ts_recent = lwip_ntohl(tsval);
|
||||
/* Enable sending timestamps in every segment now that we know
|
||||
the remote host supports it. */
|
||||
pcb->flags |= TF_TIMESTAMP;
|
||||
} else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
|
||||
pcb->ts_recent = ntohl(tsval);
|
||||
pcb->ts_recent = lwip_ntohl(tsval);
|
||||
}
|
||||
/* Advance to next option (6 bytes already read) */
|
||||
tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "lwip/stats.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
@ -115,12 +114,12 @@ tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
|
|||
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
|
||||
(p->len >= TCP_HLEN + optlen));
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->src = lwip_htons(pcb->local_port);
|
||||
tcphdr->dest = lwip_htons(pcb->remote_port);
|
||||
tcphdr->seqno = seqno_be;
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
|
||||
TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
|
||||
tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
|
||||
tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
|
||||
tcphdr->chksum = 0;
|
||||
tcphdr->urgp = 0;
|
||||
|
||||
|
@ -205,9 +204,9 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
|
|||
return NULL;
|
||||
}
|
||||
seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
|
||||
seg->tcphdr->src = htons(pcb->local_port);
|
||||
seg->tcphdr->dest = htons(pcb->remote_port);
|
||||
seg->tcphdr->seqno = htonl(seqno);
|
||||
seg->tcphdr->src = lwip_htons(pcb->local_port);
|
||||
seg->tcphdr->dest = lwip_htons(pcb->remote_port);
|
||||
seg->tcphdr->seqno = lwip_htonl(seqno);
|
||||
/* ackno is set in tcp_output */
|
||||
TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
|
||||
/* wnd and chksum are set in tcp_output */
|
||||
|
@ -225,7 +224,7 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
|
|||
* @param length size of the pbuf's payload.
|
||||
* @param max_length maximum usable size of payload+oversize.
|
||||
* @param oversize pointer to a u16_t that will receive the number of usable tail bytes.
|
||||
* @param pcb The TCP connection that willo enqueue the pbuf.
|
||||
* @param pcb The TCP connection that will enqueue the pbuf.
|
||||
* @param apiflags API flags given to tcp_write.
|
||||
* @param first_seg true when this pbuf will be used in the first enqueued segment.
|
||||
*/
|
||||
|
@ -243,7 +242,6 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
|
|||
LWIP_UNUSED_ARG(pcb);
|
||||
LWIP_UNUSED_ARG(apiflags);
|
||||
LWIP_UNUSED_ARG(first_seg);
|
||||
/* always create MSS-sized pbufs */
|
||||
alloc = max_length;
|
||||
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
if (length < max_length) {
|
||||
|
@ -350,6 +348,7 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup tcp_raw
|
||||
* Write data for sending (but does not send it immediately).
|
||||
*
|
||||
* It waits in the expectation of more data being sent soon (as
|
||||
|
@ -378,6 +377,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
u16_t oversize = 0;
|
||||
u16_t oversize_used = 0;
|
||||
#endif /* TCP_OVERSIZE */
|
||||
u16_t extendlen = 0;
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
u16_t concat_chksum = 0;
|
||||
u8_t concat_chksum_swapped = 0;
|
||||
|
@ -481,6 +481,10 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
/*
|
||||
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
|
||||
*
|
||||
* As an exception when NOT copying the data, if the given data buffer
|
||||
* directly follows the last unsent data buffer in memory, extend the last
|
||||
* ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation.
|
||||
*
|
||||
* We don't extend segments containing SYN/FIN flags or options
|
||||
* (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
|
||||
* the end.
|
||||
|
@ -507,12 +511,24 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
#if TCP_CHECKSUM_ON_COPY
|
||||
concat_chksummed += seglen;
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
queuelen += pbuf_clen(concat_p);
|
||||
} else {
|
||||
/* Data is not copied */
|
||||
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
/* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */
|
||||
struct pbuf *p;
|
||||
for (p = last_unsent->p; p->next != NULL; p = p->next);
|
||||
if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) {
|
||||
LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0);
|
||||
extendlen = seglen;
|
||||
} else {
|
||||
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
/* reference the non-volatile payload data */
|
||||
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
|
||||
queuelen += pbuf_clen(concat_p);
|
||||
}
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
/* calculate the checksum of nocopy-data */
|
||||
|
@ -520,12 +536,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
&concat_chksum, &concat_chksum_swapped);
|
||||
concat_chksummed += seglen;
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
/* reference the non-volatile payload data */
|
||||
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
|
||||
}
|
||||
|
||||
pos += seglen;
|
||||
queuelen += pbuf_clen(concat_p);
|
||||
}
|
||||
} else {
|
||||
#if TCP_OVERSIZE
|
||||
|
@ -633,8 +646,8 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
prev_seg = seg;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
|
||||
ntohl(seg->tcphdr->seqno),
|
||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
|
||||
lwip_ntohl(seg->tcphdr->seqno),
|
||||
lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
|
||||
|
||||
pos += seglen;
|
||||
}
|
||||
|
@ -670,26 +683,40 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||
#endif /* TCP_OVERSIZE */
|
||||
|
||||
/*
|
||||
* Phase 2: concat_p can be concatenated onto last_unsent->p
|
||||
* Phase 2: concat_p can be concatenated onto last_unsent->p, unless we
|
||||
* determined that the last ROM pbuf can be extended to include the new data.
|
||||
*/
|
||||
if (concat_p != NULL) {
|
||||
LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
|
||||
(last_unsent != NULL));
|
||||
pbuf_cat(last_unsent->p, concat_p);
|
||||
last_unsent->len += concat_p->tot_len;
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
if (concat_chksummed) {
|
||||
/*if concat checksumm swapped - swap it back */
|
||||
if (concat_chksum_swapped) {
|
||||
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
|
||||
}
|
||||
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
|
||||
&last_unsent->chksum_swapped);
|
||||
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
|
||||
} else if (extendlen > 0) {
|
||||
struct pbuf *p;
|
||||
LWIP_ASSERT("tcp_write: extension of reference requires reference",
|
||||
last_unsent != NULL && last_unsent->p != NULL);
|
||||
for (p = last_unsent->p; p->next != NULL; p = p->next) {
|
||||
p->tot_len += extendlen;
|
||||
}
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
p->tot_len += extendlen;
|
||||
p->len += extendlen;
|
||||
last_unsent->len += extendlen;
|
||||
}
|
||||
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
if (concat_chksummed) {
|
||||
LWIP_ASSERT("tcp_write: concat checksum needs concatenated data",
|
||||
concat_p != NULL || extendlen > 0);
|
||||
/*if concat checksumm swapped - swap it back */
|
||||
if (concat_chksum_swapped) {
|
||||
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
|
||||
}
|
||||
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
|
||||
&last_unsent->chksum_swapped);
|
||||
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
|
||||
}
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
|
||||
/*
|
||||
* Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
|
||||
* is harmless
|
||||
|
@ -808,8 +835,8 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
|
|||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
|
||||
("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
|
||||
ntohl(seg->tcphdr->seqno),
|
||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||
lwip_ntohl(seg->tcphdr->seqno),
|
||||
lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||
(u16_t)flags));
|
||||
|
||||
/* Now append seg to pcb->unsent queue */
|
||||
|
@ -856,8 +883,8 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
|
|||
{
|
||||
/* Pad with two NOP options to make everything nicely aligned */
|
||||
opts[0] = PP_HTONL(0x0101080A);
|
||||
opts[1] = htonl(sys_now());
|
||||
opts[2] = htonl(pcb->ts_recent);
|
||||
opts[1] = lwip_htonl(sys_now());
|
||||
opts[2] = lwip_htonl(pcb->ts_recent);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -874,7 +901,8 @@ tcp_build_wnd_scale_option(u32_t *opts)
|
|||
}
|
||||
#endif
|
||||
|
||||
/** Send an ACK without data.
|
||||
/**
|
||||
* Send an ACK without data.
|
||||
*
|
||||
* @param pcb Protocol control block for the TCP connection to send the ACK
|
||||
*/
|
||||
|
@ -895,7 +923,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||
}
|
||||
#endif
|
||||
|
||||
p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
|
||||
p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
|
||||
if (p == NULL) {
|
||||
/* let tcp_fasttmr retry sending this ACK */
|
||||
pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
|
||||
|
@ -946,6 +974,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||
}
|
||||
|
||||
/**
|
||||
* @ingroup tcp_raw
|
||||
* Find out what we can send and send it
|
||||
*
|
||||
* @param pcb Protocol control block for the TCP connection to send data
|
||||
|
@ -987,7 +1016,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
*/
|
||||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
return tcp_send_empty_ack(pcb);
|
||||
}
|
||||
|
||||
|
@ -1028,13 +1057,31 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
|
||||
", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||
lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||
}
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
/* Check if we need to start the persistent timer when the next unsent segment
|
||||
* does not fit within the remaining send window and RTO timer is not running (we
|
||||
* have no in-flight data). A traditional approach would fill the remaining window
|
||||
* with part of the unsent segment (which will engage zero-window probing upon
|
||||
* reception of the zero window update from the receiver). This ensures the
|
||||
* subsequent window update is reliably received. With the goal of being lightweight,
|
||||
* we avoid splitting the unsent segment and treat the window as already zero.
|
||||
*/
|
||||
if (seg != NULL &&
|
||||
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
|
||||
wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
|
||||
/* Start the persist timer */
|
||||
if (pcb->persist_backoff == 0) {
|
||||
pcb->persist_cnt = 0;
|
||||
pcb->persist_backoff = 1;
|
||||
}
|
||||
goto output_done;
|
||||
}
|
||||
/* data available and window allows it to be sent? */
|
||||
while (seg != NULL &&
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||
LWIP_ASSERT("RST not expected here!",
|
||||
(TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
|
||||
/* Stop sending if the nagle algorithm would prevent it
|
||||
|
@ -1051,9 +1098,9 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
#if TCP_CWND_DEBUG
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||
lwip_ntohl(seg->tcphdr->seqno) + seg->len -
|
||||
pcb->lastack,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack, i));
|
||||
lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
|
||||
++i;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
|
@ -1074,7 +1121,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
if (pcb->state != SYN_SENT) {
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
}
|
||||
snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
|
||||
pcb->snd_nxt = snd_nxt;
|
||||
}
|
||||
|
@ -1090,11 +1137,11 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
/* In the case of fast retransmit, the packet should not go to the tail
|
||||
* of the unacked queue, but rather somewhere before it. We need to check for
|
||||
* this case. -STJ Jul 27, 2004 */
|
||||
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
|
||||
if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
|
||||
/* add segment to before tail of unacked list, keeping the list sorted */
|
||||
struct tcp_seg **cur_seg = &(pcb->unacked);
|
||||
while (*cur_seg &&
|
||||
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
|
||||
TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
|
||||
cur_seg = &((*cur_seg)->next );
|
||||
}
|
||||
seg->next = (*cur_seg);
|
||||
|
@ -1111,6 +1158,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
}
|
||||
seg = pcb->unsent;
|
||||
}
|
||||
output_done:
|
||||
#if TCP_OVERSIZE
|
||||
if (pcb->unsent == NULL) {
|
||||
/* last unsent has been removed, reset unsent_oversize */
|
||||
|
@ -1145,18 +1193,18 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
|
|||
|
||||
/* The TCP header has already been constructed, but the ackno and
|
||||
wnd fields remain. */
|
||||
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
|
||||
|
||||
/* advertise our receive window size in this TCP segment */
|
||||
#if LWIP_WND_SCALE
|
||||
if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
|
||||
/* The Window field in a SYN segment itself (the only type where we send
|
||||
the window scale option) is never scaled. */
|
||||
seg->tcphdr->wnd = htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
|
||||
seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
|
||||
} else
|
||||
#endif /* LWIP_WND_SCALE */
|
||||
{
|
||||
seg->tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
|
||||
seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
|
||||
}
|
||||
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
|
||||
|
@ -1198,12 +1246,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
|
|||
|
||||
if (pcb->rttest == 0) {
|
||||
pcb->rttest = tcp_ticks;
|
||||
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
||||
pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
|
||||
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
||||
lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
|
||||
seg->len));
|
||||
|
||||
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
|
||||
|
@ -1301,10 +1349,10 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
|||
(p->len >= sizeof(struct tcp_hdr)));
|
||||
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
tcphdr->src = htons(local_port);
|
||||
tcphdr->dest = htons(remote_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
tcphdr->src = lwip_htons(local_port);
|
||||
tcphdr->dest = lwip_htons(remote_port);
|
||||
tcphdr->seqno = lwip_htonl(seqno);
|
||||
tcphdr->ackno = lwip_htonl(ackno);
|
||||
TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
|
||||
#if LWIP_WND_SCALE
|
||||
tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
|
||||
|
@ -1376,7 +1424,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
|
|||
/**
|
||||
* Requeue the first unacked segment for retransmission
|
||||
*
|
||||
* Called by tcp_receive() for fast retramsmit.
|
||||
* Called by tcp_receive() for fast retransmit.
|
||||
*
|
||||
* @param pcb the tcp_pcb for which to retransmit the first unacked segment
|
||||
*/
|
||||
|
@ -1397,7 +1445,7 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
|||
|
||||
cur_seg = &(pcb->unsent);
|
||||
while (*cur_seg &&
|
||||
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
|
||||
TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
|
||||
cur_seg = &((*cur_seg)->next );
|
||||
}
|
||||
seg->next = *cur_seg;
|
||||
|
@ -1435,7 +1483,7 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
|
|||
("tcp_receive: dupacks %"U16_F" (%"U32_F
|
||||
"), fast retransmit %"U32_F"\n",
|
||||
(u16_t)pcb->dupacks, pcb->lastack,
|
||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
lwip_ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
tcp_rexmit(pcb);
|
||||
|
||||
/* Set ssthresh to half of the minimum of the current
|
||||
|
@ -1486,7 +1534,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
|
||||
tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
|
||||
|
||||
p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
|
||||
p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1));
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("tcp_keepalive: could not allocate memory for pbuf\n"));
|
||||
|
@ -1535,6 +1583,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||
struct tcp_seg *seg;
|
||||
u16_t len;
|
||||
u8_t is_fin;
|
||||
u32_t snd_nxt;
|
||||
struct netif *netif;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
|
||||
|
@ -1579,6 +1628,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||
pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
|
||||
}
|
||||
|
||||
/* The byte may be acknowledged without the window being opened. */
|
||||
snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
|
||||
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
|
||||
pcb->snd_nxt = snd_nxt;
|
||||
}
|
||||
|
||||
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
|
||||
if (netif == NULL) {
|
||||
err = ERR_RTE;
|
||||
|
|
|
@ -179,7 +179,7 @@ void sys_timeouts_init(void)
|
|||
for (i = 1; 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, (void*)(size_t)&lwip_cyclic_timers[i]);
|
||||
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
||||
}
|
||||
|
||||
/* Initialise timestamp for sys_check_timeouts */
|
||||
|
@ -360,7 +360,6 @@ sys_check_timeouts(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if NO_SYS
|
||||
/** 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
|
||||
|
@ -371,7 +370,6 @@ sys_restart_timeouts(void)
|
|||
{
|
||||
timeouts_last_time = sys_now();
|
||||
}
|
||||
#endif /* NO_SYS */
|
||||
|
||||
/** Return the time left before the next timeout is due. If no timeouts are
|
||||
* enqueued, returns 0xffffffff
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
/**
|
||||
* @file
|
||||
* User Datagram Protocol module\n
|
||||
* The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n
|
||||
* See also @ref udp_raw
|
||||
*
|
||||
* @defgroup udp_raw UDP
|
||||
* @ingroup callbackstyle_api
|
||||
* User Datagram Protocol module\n
|
||||
* @see @ref raw_api and @ref netconn
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -36,19 +42,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup udp_raw UDP
|
||||
* @ingroup raw_api
|
||||
* User Datagram Protocol module\n
|
||||
* @see @ref raw_api and @ref netconn
|
||||
*/
|
||||
|
||||
/* udp.c
|
||||
*
|
||||
* The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).
|
||||
*
|
||||
*/
|
||||
|
||||
/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'!
|
||||
*/
|
||||
|
||||
|
@ -63,7 +56,6 @@
|
|||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/icmp6.h"
|
||||
|
@ -124,24 +116,6 @@ again:
|
|||
}
|
||||
}
|
||||
return udp_port;
|
||||
#if 0
|
||||
struct udp_pcb *ipcb = udp_pcbs;
|
||||
while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
|
||||
if (ipcb->local_port == udp_port) {
|
||||
/* port is already used by another udp_pcb */
|
||||
udp_port++;
|
||||
/* restart scanning all udp pcbs */
|
||||
ipcb = udp_pcbs;
|
||||
} else {
|
||||
/* go on with next udp pcb */
|
||||
ipcb = ipcb->next;
|
||||
}
|
||||
}
|
||||
if (ipcb != NULL) {
|
||||
return 0;
|
||||
}
|
||||
return udp_port;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Common code to see if the current input packet matches the pcb
|
||||
|
@ -186,19 +160,12 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast)
|
|||
}
|
||||
} else
|
||||
#endif /* LWIP_IPV4 */
|
||||
/* Handle IPv4 and IPv6: all, multicast or exact match */
|
||||
if (ip_addr_isany(&pcb->local_ip) ||
|
||||
#if LWIP_IPV6_MLD
|
||||
(ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) ||
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
#if LWIP_IGMP
|
||||
(!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
|
||||
/* Handle IPv4 and IPv6: 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;
|
||||
}
|
||||
|
||||
|
@ -250,17 +217,17 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||
|
||||
/* convert src and dest ports to host byte order */
|
||||
src = ntohs(udphdr->src);
|
||||
dest = ntohs(udphdr->dest);
|
||||
src = lwip_ntohs(udphdr->src);
|
||||
dest = lwip_ntohs(udphdr->dest);
|
||||
|
||||
udp_debug_print(udphdr);
|
||||
|
||||
/* print the UDP source and destination */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr());
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest)));
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr());
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src)));
|
||||
|
||||
pcb = NULL;
|
||||
prev = NULL;
|
||||
|
@ -339,7 +306,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
#if LWIP_UDPLITE
|
||||
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
|
||||
/* Do the UDP Lite checksum */
|
||||
u16_t chklen = ntohs(udphdr->len);
|
||||
u16_t chklen = lwip_ntohs(udphdr->len);
|
||||
if (chklen < sizeof(struct udp_hdr)) {
|
||||
if (chklen == 0) {
|
||||
/* For UDP-Lite, checksum length of 0 means checksum
|
||||
|
@ -437,7 +404,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
destination address was broadcast/multicast. */
|
||||
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN);
|
||||
pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN));
|
||||
icmp_port_unreach(ip_current_is_v6(), p);
|
||||
}
|
||||
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
||||
|
@ -579,7 +546,12 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
|
|||
#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */
|
||||
|
||||
/* find the outgoing network interface for this packet */
|
||||
netif = ip_route(&pcb->local_ip, dst_ip_route);
|
||||
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
||||
/* Don't call ip_route() with IP_ANY_TYPE */
|
||||
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route);
|
||||
} else {
|
||||
netif = ip_route(&pcb->local_ip, dst_ip_route);
|
||||
}
|
||||
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
|
@ -670,7 +642,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_i
|
|||
* this could be an old address if netif->ip_addr has changed */
|
||||
if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {
|
||||
/* local_ip doesn't match, drop the packet */
|
||||
return ERR_VAL;
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = &pcb->local_ip;
|
||||
|
@ -760,8 +732,8 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
|
|||
(q->len >= sizeof(struct udp_hdr)));
|
||||
/* q now represents the packet to be sent */
|
||||
udphdr = (struct udp_hdr *)q->payload;
|
||||
udphdr->src = htons(pcb->local_port);
|
||||
udphdr->dest = htons(dst_port);
|
||||
udphdr->src = lwip_htons(pcb->local_port);
|
||||
udphdr->dest = lwip_htons(dst_port);
|
||||
/* in UDP, 0 checksum means 'no checksum' */
|
||||
udphdr->chksum = 0x0000;
|
||||
|
||||
|
@ -794,7 +766,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
|
|||
chklen_hdr = 0;
|
||||
chklen = q->tot_len;
|
||||
}
|
||||
udphdr->len = htons(chklen_hdr);
|
||||
udphdr->len = lwip_htons(chklen_hdr);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
|
||||
|
@ -825,7 +797,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
|
|||
#endif /* LWIP_UDPLITE */
|
||||
{ /* UDP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||
udphdr->len = htons(q->tot_len);
|
||||
udphdr->len = lwip_htons(q->tot_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
|
||||
|
@ -859,7 +831,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
|
|||
|
||||
/* Determine TTL to use */
|
||||
#if LWIP_MULTICAST_TX_OPTIONS
|
||||
ttl = (ip_addr_ismulticast(dst_ip) ? pcb->mcast_ttl : pcb->ttl);
|
||||
ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl);
|
||||
#else /* LWIP_MULTICAST_TX_OPTIONS */
|
||||
ttl = pcb->ttl;
|
||||
#endif /* LWIP_MULTICAST_TX_OPTIONS */
|
||||
|
@ -891,7 +863,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
|
|||
* Bind an UDP PCB.
|
||||
*
|
||||
* @param pcb UDP PCB to be bound with a local address ipaddr and port.
|
||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
||||
* @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
* @param port local UDP port to bind with. Use 0 to automatically bind
|
||||
* to a random port between UDP_LOCAL_PORT_RANGE_START and
|
||||
|
@ -915,12 +887,12 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|||
#if LWIP_IPV4
|
||||
/* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
|
||||
if (ipaddr == NULL) {
|
||||
ipaddr = IP_ADDR_ANY;
|
||||
ipaddr = IP4_ADDR_ANY;
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
/* still need to check for ipaddr == NULL in IPv6 only case */
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
@ -1141,7 +1113,7 @@ udp_new(void)
|
|||
memset(pcb, 0, sizeof(struct udp_pcb));
|
||||
pcb->ttl = UDP_TTL;
|
||||
#if LWIP_MULTICAST_TX_OPTIONS
|
||||
pcb->mcast_ttl = UDP_TTL;
|
||||
udp_set_multicast_ttl(pcb, UDP_TTL);
|
||||
#endif /* LWIP_MULTICAST_TX_OPTIONS */
|
||||
}
|
||||
return pcb;
|
||||
|
@ -1151,7 +1123,9 @@ udp_new(void)
|
|||
* @ingroup udp_raw
|
||||
* Create a UDP PCB for specific IP type.
|
||||
*
|
||||
* @param type IP address type, see IPADDR_TYPE_XX definitions.
|
||||
* @param type IP address type, see @ref lwip_ip_addr_type definitions.
|
||||
* If you want to listen to IPv4 and IPv6 (dual-stack) packets,
|
||||
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
|
||||
* @return The UDP PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
|
@ -1173,32 +1147,26 @@ udp_new_ip_type(u8_t type)
|
|||
return pcb;
|
||||
}
|
||||
|
||||
#if LWIP_IPV4
|
||||
/** This function is called from netif.c when address is changed
|
||||
*
|
||||
* @param old_addr IPv4 address of the netif before change
|
||||
* @param new_addr IPv4 address of the netif after change
|
||||
* @param old_addr IP address of the netif before change
|
||||
* @param new_addr IP address of the netif after change
|
||||
*/
|
||||
void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr)
|
||||
void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr)
|
||||
{
|
||||
struct udp_pcb* upcb;
|
||||
|
||||
if (!ip4_addr_isany(new_addr)) {
|
||||
if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) {
|
||||
for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) {
|
||||
/* Is this an IPv4 pcb? */
|
||||
if (IP_IS_V4_VAL(upcb->local_ip)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (!ip4_addr_isany(ip_2_ip4(&upcb->local_ip)) &&
|
||||
ip4_addr_cmp(ip_2_ip4(&upcb->local_ip), old_addr)) {
|
||||
/* The PCB is bound to the old ipaddr and
|
||||
* is set to bound to the new one instead */
|
||||
ip_addr_copy_from_ip4(upcb->local_ip, *new_addr);
|
||||
}
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&upcb->local_ip, old_addr)) {
|
||||
/* The PCB is bound to the old ipaddr and
|
||||
* is set to bound to the new one instead */
|
||||
ip_addr_copy(upcb->local_ip, *new_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
#if UDP_DEBUG
|
||||
/**
|
||||
|
@ -1212,10 +1180,10 @@ udp_debug_print(struct udp_hdr *udphdr)
|
|||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
||||
lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
|
||||
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
||||
lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* UDP_DEBUG */
|
||||
|
|
|
@ -43,8 +43,7 @@
|
|||
/* 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/arch.h"
|
||||
#include "lwip/netbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
@ -90,6 +89,7 @@ extern "C" {
|
|||
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
|
||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
|
||||
#else /* LWIP_IPV6 */
|
||||
#define NETCONNTYPE_ISIPV6(t) (0)
|
||||
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
|
||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
@ -139,7 +139,32 @@ enum netconn_state {
|
|||
NETCONN_CLOSE
|
||||
};
|
||||
|
||||
/** Use to inform the callback function about changes */
|
||||
/** Used to inform the callback function about changes
|
||||
*
|
||||
* Event explanation:
|
||||
*
|
||||
* In the netconn implementation, there are three ways to block a client:
|
||||
*
|
||||
* - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept())
|
||||
* - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data())
|
||||
* - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write())
|
||||
*
|
||||
* The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking
|
||||
* connections, you need to know in advance whether a call to a netconn function call would block or not,
|
||||
* and these events tell you about that.
|
||||
*
|
||||
* RCVPLUS events say: Safe to perform a potentially blocking call call once more.
|
||||
* They are counted in sockets - three RCVPLUS events for accept mbox means you are safe
|
||||
* to call netconn_accept 3 times without being blocked.
|
||||
* Same thing for receive mbox.
|
||||
*
|
||||
* RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged".
|
||||
* Socket implementation decrements the counter.
|
||||
*
|
||||
* For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something.
|
||||
* SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again.
|
||||
* A SENDMINUS event occurs when the next call to a netconn_send() would be blocking.
|
||||
*/
|
||||
enum netconn_evt {
|
||||
NETCONN_EVT_RCVPLUS,
|
||||
NETCONN_EVT_RCVMINUS,
|
||||
|
@ -327,7 +352,7 @@ err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
|||
|
||||
#if LWIP_IPV6
|
||||
/** @ingroup netconn_common
|
||||
* TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY)
|
||||
* 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; \
|
||||
|
|
|
@ -161,28 +161,6 @@
|
|||
#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/** Set this to 1 on platforms where strnstr is not available */
|
||||
#if !defined LWIP_HTTPD_STRNSTR_PRIVATE || defined __DOXYGEN__
|
||||
#define LWIP_HTTPD_STRNSTR_PRIVATE 1
|
||||
#endif
|
||||
|
||||
/** Set this to 1 on platforms where stricmp is not available */
|
||||
#if !defined LWIP_HTTPD_STRICMP_PRIVATE || defined __DOXYGEN__
|
||||
#define LWIP_HTTPD_STRICMP_PRIVATE 0
|
||||
#endif
|
||||
|
||||
/** Define this to a smaller function if you have itoa() at hand... */
|
||||
#if !defined LWIP_HTTPD_ITOA || defined __DOXYGEN__
|
||||
#if !defined LWIP_HTTPD_ITOA_PRIVATE || defined __DOXYGEN__
|
||||
#define LWIP_HTTPD_ITOA_PRIVATE 1
|
||||
#endif
|
||||
#if LWIP_HTTPD_ITOA_PRIVATE
|
||||
#define LWIP_HTTPD_ITOA(buffer, bufsize, number) httpd_itoa(number, buffer)
|
||||
#else
|
||||
#define LWIP_HTTPD_ITOA(buffer, bufsize, number) snprintf(buffer, bufsize, "%d", number)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Set this to one to show error pages when parsing a request fails instead
|
||||
of simply closing the connection. */
|
||||
#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* @file
|
||||
* MDNS responder
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* 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: Erik Ekman <erik@kryo.se>
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_MDNS_H
|
||||
#define LWIP_HDR_MDNS_H
|
||||
|
||||
#include "lwip/apps/mdns_opts.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#if LWIP_MDNS_RESPONDER
|
||||
|
||||
enum mdns_sd_proto {
|
||||
DNSSD_PROTO_UDP = 0,
|
||||
DNSSD_PROTO_TCP = 1
|
||||
};
|
||||
|
||||
#define MDNS_LABEL_MAXLEN 63
|
||||
|
||||
struct mdns_host;
|
||||
struct mdns_service;
|
||||
|
||||
/** Callback function to add text to a reply, called when generating the reply */
|
||||
typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata);
|
||||
|
||||
void mdns_resp_init(void);
|
||||
|
||||
err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl);
|
||||
err_t mdns_resp_remove_netif(struct netif *netif);
|
||||
|
||||
err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len);
|
||||
void mdns_resp_netif_settings_changed(struct netif *netif);
|
||||
|
||||
#endif /* LWIP_MDNS_RESPONDER */
|
||||
|
||||
#endif /* LWIP_HDR_MDNS_H */
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file
|
||||
* MDNS responder
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* 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: Erik Ekman <erik@kryo.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_APPS_MDNS_OPTS_H
|
||||
#define LWIP_HDR_APPS_MDNS_OPTS_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/**
|
||||
* @defgroup mdns_opts Options
|
||||
* @ingroup mdns
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS
|
||||
* transport. IGMP is needed for IPv4 multicast.
|
||||
*/
|
||||
#ifndef LWIP_MDNS_RESPONDER
|
||||
#define LWIP_MDNS_RESPONDER 0
|
||||
#endif /* LWIP_MDNS_RESPONDER */
|
||||
|
||||
/** The maximum number of services per netif */
|
||||
#ifndef MDNS_MAX_SERVICES
|
||||
#define MDNS_MAX_SERVICES 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MDNS_DEBUG: Enable debugging for multicast DNS.
|
||||
*/
|
||||
#ifndef MDNS_DEBUG
|
||||
#define MDNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file
|
||||
* MDNS responder private definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* 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: Erik Ekman <erik@kryo.se>
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_MDNS_PRIV_H
|
||||
#define LWIP_HDR_MDNS_PRIV_H
|
||||
|
||||
#include "lwip/apps/mdns_opts.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#if LWIP_MDNS_RESPONDER
|
||||
|
||||
/* Domain struct and methods - visible for unit tests */
|
||||
|
||||
#define MDNS_DOMAIN_MAXLEN 256
|
||||
#define MDNS_READNAME_ERROR 0xFFFF
|
||||
|
||||
struct mdns_domain {
|
||||
/* Encoded domain name */
|
||||
u8_t name[MDNS_DOMAIN_MAXLEN];
|
||||
/* Total length of domain name, including zero */
|
||||
u16_t length;
|
||||
/* Set if compression of this domain is not allowed */
|
||||
u8_t skip_compression;
|
||||
};
|
||||
|
||||
err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len);
|
||||
u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain);
|
||||
int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b);
|
||||
u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain);
|
||||
|
||||
#endif /* LWIP_MDNS_RESPONDER */
|
||||
|
||||
#endif /* LWIP_HDR_MDNS_PRIV_H */
|
|
@ -0,0 +1,243 @@
|
|||
/**
|
||||
* @file
|
||||
* MQTT client
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Erik Andersson
|
||||
* 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: Erik Andersson
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H
|
||||
#define LWIP_HDR_APPS_MQTT_CLIENT_H
|
||||
|
||||
#include "lwip/apps/mqtt_opts.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct mqtt_client_t mqtt_client_t;
|
||||
|
||||
/** @ingroup mqtt
|
||||
* Default MQTT port */
|
||||
#define MQTT_PORT 1883
|
||||
|
||||
/*---------------------------------------------------------------------------------------------- */
|
||||
/* Connection with server */
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Client information and connection parameters */
|
||||
struct mqtt_connect_client_info_t {
|
||||
/** Client identifier, must be set by caller */
|
||||
const char *client_id;
|
||||
/** User name and password, set to NULL if not used */
|
||||
const char* client_user;
|
||||
const char* client_pass;
|
||||
/** keep alive time in seconds, 0 to disable keep alive functionality*/
|
||||
u16_t keep_alive;
|
||||
/** will topic, set to NULL if will is not to be used,
|
||||
will_msg, will_qos and will retain are then ignored */
|
||||
const char* will_topic;
|
||||
const char* will_msg;
|
||||
u8_t will_qos;
|
||||
u8_t will_retain;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Connection status codes */
|
||||
typedef enum
|
||||
{
|
||||
MQTT_CONNECT_ACCEPTED = 0,
|
||||
MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1,
|
||||
MQTT_CONNECT_REFUSED_IDENTIFIER = 2,
|
||||
MQTT_CONNECT_REFUSED_SERVER = 3,
|
||||
MQTT_CONNECT_REFUSED_USERNAME_PASS = 4,
|
||||
MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5,
|
||||
MQTT_CONNECT_DISCONNECTED = 256,
|
||||
MQTT_CONNECT_TIMEOUT = 257
|
||||
} mqtt_connection_status_t;
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Function prototype for mqtt connection status callback. Called when
|
||||
* client has connected to the server after initiating a mqtt connection attempt by
|
||||
* calling mqtt_connect() or when connection is closed by server or an error
|
||||
*
|
||||
* @param client MQTT client itself
|
||||
* @param arg Additional argument to pass to the callback function
|
||||
* @param status Connect result code or disconnection notification @see mqtt_connection_status_t
|
||||
*
|
||||
*/
|
||||
typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Data callback flags */
|
||||
enum {
|
||||
/** Flag set when last fragment of data arrives in data callback */
|
||||
MQTT_DATA_FLAG_LAST = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Function prototype for MQTT incoming publish data callback function. Called when data
|
||||
* arrives to a subscribed topic @see mqtt_subscribe
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function
|
||||
* @param data User data, pointed object, data may not be referenced after callback return,
|
||||
NULL is passed when all publish data are delivered
|
||||
* @param len Length of publish data fragment
|
||||
* @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message
|
||||
*
|
||||
*/
|
||||
typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Function prototype for MQTT incoming publish function. Called when an incoming publish
|
||||
* arrives to a subscribed topic @see mqtt_subscribe
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function
|
||||
* @param topic Zero terminated Topic text string, topic may not be referenced after callback return
|
||||
* @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked
|
||||
*/
|
||||
typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup mqtt
|
||||
* Function prototype for mqtt request callback. Called when a subscribe, unsubscribe
|
||||
* or publish request has completed
|
||||
* @param arg Pointer to user data supplied when invoking request
|
||||
* @param err ERR_OK on success
|
||||
* ERR_TIMEOUT if no response was received within timeout,
|
||||
* ERR_ABRT if (un)subscribe was denied
|
||||
*/
|
||||
typedef void (*mqtt_request_cb_t)(void *arg, err_t err);
|
||||
|
||||
|
||||
/**
|
||||
* Pending request item, binds application callback to pending server requests
|
||||
*/
|
||||
struct mqtt_request_t
|
||||
{
|
||||
/** Next item in list, NULL means this is the last in chain,
|
||||
next pointing at itself means request is unallocated */
|
||||
struct mqtt_request_t *next;
|
||||
/** Callback to upper layer */
|
||||
mqtt_request_cb_t cb;
|
||||
void *arg;
|
||||
/** MQTT packet identifier */
|
||||
u16_t pkt_id;
|
||||
/** Expire time relative to element before this */
|
||||
u16_t timeout_diff;
|
||||
};
|
||||
|
||||
/** Ring buffer */
|
||||
struct mqtt_ringbuf_t {
|
||||
u16_t put;
|
||||
u16_t get;
|
||||
u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE];
|
||||
};
|
||||
|
||||
/** MQTT client */
|
||||
struct mqtt_client_t
|
||||
{
|
||||
/** Timers and timeouts */
|
||||
u16_t cyclic_tick;
|
||||
u16_t keep_alive;
|
||||
u16_t server_watchdog;
|
||||
/** Packet identifier generator*/
|
||||
u16_t pkt_id_seq;
|
||||
/** Packet identifier of pending incoming publish */
|
||||
u16_t inpub_pkt_id;
|
||||
/** Connection state */
|
||||
u8_t conn_state;
|
||||
struct tcp_pcb *conn;
|
||||
/** Connection callback */
|
||||
void *connect_arg;
|
||||
mqtt_connection_cb_t connect_cb;
|
||||
/** Pending requests to server */
|
||||
struct mqtt_request_t *pend_req_queue;
|
||||
struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT];
|
||||
void *inpub_arg;
|
||||
/** Incoming data callback */
|
||||
mqtt_incoming_data_cb_t data_cb;
|
||||
mqtt_incoming_publish_cb_t pub_cb;
|
||||
/** Input */
|
||||
u32_t msg_idx;
|
||||
u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN];
|
||||
/** Output ring-buffer */
|
||||
struct mqtt_ringbuf_t output;
|
||||
};
|
||||
|
||||
|
||||
/** Connect to server */
|
||||
err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg,
|
||||
const struct mqtt_connect_client_info_t *client_info);
|
||||
|
||||
/** Disconnect from server */
|
||||
void mqtt_disconnect(mqtt_client_t *client);
|
||||
|
||||
/** Create new client */
|
||||
mqtt_client_t *mqtt_client_new(void);
|
||||
|
||||
/** Check connection status */
|
||||
u8_t mqtt_client_is_connected(mqtt_client_t *client);
|
||||
|
||||
/** Set callback to call for incoming publish */
|
||||
void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t,
|
||||
mqtt_incoming_data_cb_t data_cb, void *arg);
|
||||
|
||||
/** Common function for subscribe and unsubscribe */
|
||||
err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub);
|
||||
|
||||
/** @ingroup mqtt
|
||||
*Subscribe to topic */
|
||||
#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1)
|
||||
/** @ingroup mqtt
|
||||
* Unsubscribe to topic */
|
||||
#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0)
|
||||
|
||||
|
||||
/** Publish data to topic */
|
||||
err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
|
||||
mqtt_request_cb_t cb, void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* @file
|
||||
* MQTT client options
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Erik Andersson
|
||||
* 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: Erik Andersson
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_APPS_MQTT_OPTS_H
|
||||
#define LWIP_HDR_APPS_MQTT_OPTS_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup mqtt_opts Options
|
||||
* @ingroup mqtt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads
|
||||
*/
|
||||
#ifndef MQTT_OUTPUT_RINGBUF_SIZE
|
||||
#define MQTT_OUTPUT_RINGBUF_SIZE 256
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8
|
||||
* If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8
|
||||
*/
|
||||
#ifndef MQTT_VAR_HEADER_BUFFER_LEN
|
||||
#define MQTT_VAR_HEADER_BUFFER_LEN 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum number of pending subscribe, unsubscribe and publish requests to server .
|
||||
*/
|
||||
#ifndef MQTT_REQ_MAX_IN_FLIGHT
|
||||
#define MQTT_REQ_MAX_IN_FLIGHT 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Seconds between each cyclic timer call.
|
||||
*/
|
||||
#ifndef MQTT_CYCLIC_TIMER_INTERVAL
|
||||
#define MQTT_CYCLIC_TIMER_INTERVAL 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Publish, subscribe and unsubscribe request timeout in seconds.
|
||||
*/
|
||||
#ifndef MQTT_REQ_TIMEOUT
|
||||
#define MQTT_REQ_TIMEOUT 30
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Seconds for MQTT connect response timeout after sending connect request
|
||||
*/
|
||||
#ifndef MQTT_CONNECT_TIMOUT
|
||||
#define MQTT_CONNECT_TIMOUT 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */
|
|
@ -40,16 +40,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/** Since there's no standard function for case-insensitive string comparision,
|
||||
* we need another define here:
|
||||
* define this to stricmp() for windows or strcasecmp() for linux.
|
||||
* If not defined, comparision is case sensitive and the provided hostname must be
|
||||
* uppercase.
|
||||
*/
|
||||
#if !defined NETBIOS_STRCMP || defined __DOXYGEN__
|
||||
#define NETBIOS_STRCMP(str1, str2) strcmp(str1, str2)
|
||||
#endif
|
||||
|
||||
/** NetBIOS name of lwip device
|
||||
* This must be uppercase until NETBIOS_STRCMP() is defined to a string
|
||||
* comparision function that is case insensitive.
|
||||
|
|
|
@ -99,6 +99,7 @@ void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst);
|
|||
|
||||
err_t snmp_send_trap_generic(s32_t generic_trap);
|
||||
err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds);
|
||||
err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds);
|
||||
|
||||
#define SNMP_AUTH_TRAPS_DISABLED 0
|
||||
#define SNMP_AUTH_TRAPS_ENABLED 1
|
||||
|
|
|
@ -200,7 +200,7 @@ struct snmp_node_instance
|
|||
u8_t asn1_type;
|
||||
/** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */
|
||||
snmp_access_t access;
|
||||
|
||||
|
||||
/** returns object value for the given object identifier. Return values <0 to indicate an error */
|
||||
node_instance_get_value_method get_value;
|
||||
/** tests length and/or range BEFORE setting */
|
||||
|
@ -278,7 +278,7 @@ struct snmp_next_oid_state
|
|||
u32_t* next_oid;
|
||||
u8_t next_oid_len;
|
||||
u8_t next_oid_max_len;
|
||||
|
||||
|
||||
snmp_next_oid_status_t status;
|
||||
void* reference;
|
||||
};
|
||||
|
|
|
@ -283,7 +283,11 @@
|
|||
#endif
|
||||
|
||||
#ifndef LWIP_SNMP_V3_CRYPTO
|
||||
#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3
|
||||
#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_SNMP_V3_MBEDTLS
|
||||
#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_SNMP_OPTS_H */
|
||||
|
|
|
@ -85,7 +85,7 @@ snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len
|
|||
|
||||
#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */
|
||||
|
||||
|
||||
|
||||
/** simple read-only table */
|
||||
typedef enum {
|
||||
SNMP_VARIANT_VALUE_TYPE_U32,
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/****************************************************************//**
|
||||
*
|
||||
* @file tftp_opts.h
|
||||
*
|
||||
* @author Logan Gunthorpe <logang@deltatee.com>
|
||||
*
|
||||
* @brief Trivial File Transfer Protocol (RFC 1350) implementation options
|
||||
*
|
||||
* Copyright (c) Deltatee Enterprises Ltd. 2013
|
||||
* 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: Logan Gunthorpe <logang@deltatee.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_APPS_TFTP_OPTS_H
|
||||
#define LWIP_HDR_APPS_TFTP_OPTS_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/**
|
||||
* @defgroup tftp_opts Options
|
||||
* @ingroup tftp
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enable TFTP debug messages
|
||||
*/
|
||||
#if !defined TFTP_DEBUG || defined __DOXYGEN__
|
||||
#define TFTP_DEBUG LWIP_DBG_ON
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TFTP server port
|
||||
*/
|
||||
#if !defined TFTP_PORT || defined __DOXYGEN__
|
||||
#define TFTP_PORT 69
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TFTP timeout
|
||||
*/
|
||||
#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__
|
||||
#define TFTP_TIMEOUT_MSECS 10000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Max. number of retries when a file is read from server
|
||||
*/
|
||||
#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__
|
||||
#define TFTP_MAX_RETRIES 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TFTP timer cyclic interval
|
||||
*/
|
||||
#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__
|
||||
#define TFTP_TIMER_MSECS 50
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Max. length of TFTP filename
|
||||
*/
|
||||
#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__
|
||||
#define TFTP_MAX_FILENAME_LEN 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Max. length of TFTP mode
|
||||
*/
|
||||
#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__
|
||||
#define TFTP_MAX_MODE_LEN 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */
|
|
@ -0,0 +1,94 @@
|
|||
/****************************************************************//**
|
||||
*
|
||||
* @file tftp_server.h
|
||||
*
|
||||
* @author Logan Gunthorpe <logang@deltatee.com>
|
||||
*
|
||||
* @brief Trivial File Transfer Protocol (RFC 1350)
|
||||
*
|
||||
* Copyright (c) Deltatee Enterprises Ltd. 2013
|
||||
* 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: Logan Gunthorpe <logang@deltatee.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_APPS_TFTP_SERVER_H
|
||||
#define LWIP_HDR_APPS_TFTP_SERVER_H
|
||||
|
||||
#include "lwip/apps/tftp_opts.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @ingroup tftp
|
||||
* TFTP context containing callback functions for TFTP transfers
|
||||
*/
|
||||
struct tftp_context {
|
||||
/**
|
||||
* Open file for read/write.
|
||||
* @param fname Filename
|
||||
* @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail)
|
||||
* @param write Flag indicating read (0) or write (!= 0) access
|
||||
* @returns File handle supplied to other functions
|
||||
*/
|
||||
void* (*open)(const char* fname, const char* mode, u8_t write);
|
||||
/**
|
||||
* Close file handle
|
||||
* @param handle File handle returned by open()
|
||||
*/
|
||||
void (*close)(void* handle);
|
||||
/**
|
||||
* Read from file
|
||||
* @param handle File handle returned by open()
|
||||
* @param buf Target buffer to copy read data to
|
||||
* @param bytes Number of bytes to copy to buf
|
||||
* @returns >= 0: Success; < 0: Error
|
||||
*/
|
||||
int (*read)(void* handle, void* buf, int bytes);
|
||||
/**
|
||||
* Write to file
|
||||
* @param handle File handle returned by open()
|
||||
* @param pbuf PBUF adjusted such that payload pointer points
|
||||
* to the beginning of write data. In other words,
|
||||
* TFTP headers are stripped off.
|
||||
* @returns >= 0: Success; < 0: Error
|
||||
*/
|
||||
int (*write)(void* handle, struct pbuf* p);
|
||||
};
|
||||
|
||||
err_t tftp_init(const struct tftp_context* ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */
|
|
@ -47,12 +47,67 @@
|
|||
|
||||
#include "arch/cc.h"
|
||||
|
||||
/**
|
||||
* @defgroup compiler_abstraction Compiler/platform abstraction
|
||||
* @ingroup sys_layer
|
||||
* All defines related to this section must not be placed in lwipopts.h,
|
||||
* but in arch/cc.h!
|
||||
* These options cannot be \#defined in lwipopts.h since they are not options
|
||||
* of lwIP itself, but options of the lwIP port to your system.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Define the byte order of the system.
|
||||
* Needed for conversion of network data to host byte order.
|
||||
* Allowed values: LITTLE_ENDIAN and BIG_ENDIAN
|
||||
*/
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
/** Define random number generator function of your system */
|
||||
#ifndef LWIP_RAND
|
||||
#define LWIP_RAND() ((u32_t)rand())
|
||||
#endif
|
||||
|
||||
/** Platform specific diagnostic output.\n
|
||||
* Note the default implementation pulls in printf, which may
|
||||
* in turn pull in a lot of standard libary code. In resource-constrained
|
||||
* systems, this should be defined to something less resource-consuming.
|
||||
*/
|
||||
#ifndef LWIP_PLATFORM_DIAG
|
||||
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/** Platform specific assertion handling.\n
|
||||
* Note the default implementation pulls in printf, fflush and abort, which may
|
||||
* in turn pull in a lot of standard libary code. In resource-constrained
|
||||
* systems, this should be defined to something less resource-consuming.
|
||||
*/
|
||||
#ifndef LWIP_PLATFORM_ASSERT
|
||||
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
|
||||
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/** Define this to 1 in arch/cc.h of your port if you do not want to
|
||||
* include stddef.h header to get size_t. You need to typedef size_t
|
||||
* by yourself in this case.
|
||||
*/
|
||||
#ifndef LWIP_NO_STDDEF_H
|
||||
#define LWIP_NO_STDDEF_H 0
|
||||
#endif
|
||||
|
||||
#if !LWIP_NO_STDDEF_H
|
||||
#include <stddef.h> /* for size_t */
|
||||
#endif
|
||||
|
||||
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
||||
* the stdint.h header. This cannot be \#defined in lwipopts.h since
|
||||
* this is not an option of lwIP itself, but an option of the lwIP port
|
||||
* to your system.
|
||||
* Additionally, this header is meant to be \#included in lwipopts.h
|
||||
* (you may need to declare function prototypes in there).
|
||||
* the stdint.h header. You need to typedef the generic types listed in
|
||||
* lwip/arch.h yourself in this case (u8_t, u16_t...).
|
||||
*/
|
||||
#ifndef LWIP_NO_STDINT_H
|
||||
#define LWIP_NO_STDINT_H 0
|
||||
|
@ -71,11 +126,8 @@ typedef uintptr_t mem_ptr_t;
|
|||
#endif
|
||||
|
||||
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
||||
* the inttypes.h header. This cannot be \#defined in lwipopts.h since
|
||||
* this is not an option of lwIP itself, but an option of the lwIP port
|
||||
* to your system.
|
||||
* Additionally, this header is meant to be \#included in lwipopts.h
|
||||
* (you may need to declare function prototypes in there).
|
||||
* the inttypes.h header. You need to define the format strings listed in
|
||||
* lwip/arch.h yourself in this case (X8_F, U16_F...).
|
||||
*/
|
||||
#ifndef LWIP_NO_INTTYPES_H
|
||||
#define LWIP_NO_INTTYPES_H 0
|
||||
|
@ -85,7 +137,7 @@ typedef uintptr_t mem_ptr_t;
|
|||
#if !LWIP_NO_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#ifndef X8_F
|
||||
#define X8_F "02"PRIx8
|
||||
#define X8_F "02" PRIx8
|
||||
#endif
|
||||
#ifndef U16_F
|
||||
#define U16_F PRIu16
|
||||
|
@ -110,14 +162,31 @@ typedef uintptr_t mem_ptr_t;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/** 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
|
||||
|
||||
/** Get rid of alignment cast warnings (GCC -Wcast-align) */
|
||||
#ifndef LWIP_ALIGNMENT_CAST
|
||||
#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
|
||||
#endif
|
||||
|
||||
/** Get rid of warnings related to pointer-to-numeric and vice-versa casts,
|
||||
* e.g. "conversion from 'u8_t' to 'void *' of greater size"
|
||||
*/
|
||||
#ifndef LWIP_PTR_NUMERIC_CAST
|
||||
#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
|
||||
#endif
|
||||
|
||||
/** Allocates a memory buffer of specified size that is of sufficient size to align
|
||||
* its start address using LWIP_MEM_ALIGN.
|
||||
* You can declare your own version here e.g. to enforce alignment without adding
|
||||
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
|
||||
* requirements.
|
||||
* e.g. if you use gcc and need 32 bit alignment:
|
||||
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] __attribute__((aligned(4)))
|
||||
* or more portable:
|
||||
* requirements.\n
|
||||
* e.g. if you use gcc and need 32 bit alignment:\n
|
||||
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
|
||||
* or more portable:\n
|
||||
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
|
||||
*/
|
||||
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
|
||||
|
@ -151,175 +220,84 @@ typedef uintptr_t mem_ptr_t;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Packed structs support.
|
||||
* Placed BEFORE declaration of a packed struct.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#ifndef PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#endif /* PACK_STRUCT_BEGIN */
|
||||
|
||||
/** Packed structs support.
|
||||
* Placed AFTER declaration of a packed struct.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#ifndef PACK_STRUCT_END
|
||||
#define PACK_STRUCT_END
|
||||
#endif /* PACK_STRUCT_END */
|
||||
|
||||
/** Packed structs support.
|
||||
* Placed between end of declaration of a packed struct and trailing semicolon.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#ifndef PACK_STRUCT_STRUCT
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define PACK_STRUCT_STRUCT __attribute__((packed))
|
||||
#else
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#endif
|
||||
#endif /* PACK_STRUCT_STRUCT */
|
||||
|
||||
/** Packed structs support.
|
||||
* Wraps u32_t and u16_t members.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#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 */
|
||||
/** Packed structs support.
|
||||
* Wraps u8_t members, where some compilers warn that packing is not necessary.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#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 */
|
||||
/** Packed structs support.
|
||||
* Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#ifndef PACK_STRUCT_FLD_S
|
||||
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
|
||||
#endif /* PACK_STRUCT_FLD_S */
|
||||
|
||||
/** Packed structs support using \#include files before and after struct to be packed.\n
|
||||
* The file included BEFORE the struct is "arch/bpstruct.h".\n
|
||||
* The file included AFTER the struct is "arch/epstruct.h".\n
|
||||
* This can be used to implement struct packing on MS Visual C compilers, see
|
||||
* the Win32 port in the lwIP contrib repository for reference.
|
||||
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||
*/
|
||||
#ifdef __DOXYGEN__
|
||||
#define PACK_STRUCT_USE_INCLUDES
|
||||
#endif
|
||||
|
||||
/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */
|
||||
#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
|
||||
}
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
* 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
|
||||
|
@ -78,7 +75,6 @@ struct autoip
|
|||
};
|
||||
|
||||
|
||||
#define autoip_init() /* Compatibility define, no init needed. */
|
||||
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)
|
||||
|
@ -89,6 +85,11 @@ void autoip_tmr(void);
|
|||
void autoip_network_changed(struct netif *netif);
|
||||
u8_t autoip_supplied_address(const struct netif *netif);
|
||||
|
||||
/* for lwIP internal use by ip4.c */
|
||||
u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr);
|
||||
|
||||
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue