Upgraded lwIP to 2.0.2-STABLE
This commit is contained in:
8402
ext/lwip/CHANGELOG
Normal file → Executable file
8402
ext/lwip/CHANGELOG
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
66
ext/lwip/COPYING
Normal file → Executable file
66
ext/lwip/COPYING
Normal file → Executable file
@@ -1,33 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
9
ext/lwip/FILES
Normal file → Executable file
9
ext/lwip/FILES
Normal file → Executable file
@@ -1,4 +1,5 @@
|
|||||||
src/ - The source code for the lwIP TCP/IP stack.
|
src/ - The source code for the lwIP TCP/IP stack.
|
||||||
doc/ - The documentation for lwIP.
|
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.
|
|
||||||
|
See also the FILES file in each subdirectory.
|
||||||
|
|||||||
197
ext/lwip/README
Normal file → Executable file
197
ext/lwip/README
Normal file → Executable file
@@ -1,97 +1,100 @@
|
|||||||
INTRODUCTION
|
INTRODUCTION
|
||||||
|
|
||||||
lwIP is a small independent implementation of the TCP/IP protocol
|
lwIP is a small independent implementation of the TCP/IP protocol
|
||||||
suite that has been developed by Adam Dunkels at the Computer and
|
suite that has been developed by Adam Dunkels at the Computer and
|
||||||
Networks Architectures (CNA) lab at the Swedish Institute of Computer
|
Networks Architectures (CNA) lab at the Swedish Institute of Computer
|
||||||
Science (SICS).
|
Science (SICS).
|
||||||
|
|
||||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||||
while still having a full scale TCP. This making lwIP suitable for use
|
while still having a full scale TCP. This making lwIP suitable for use
|
||||||
in embedded systems with tens of kilobytes of free RAM and room for
|
in embedded systems with tens of kilobytes of free RAM and room for
|
||||||
around 40 kilobytes of code ROM.
|
around 40 kilobytes of code ROM.
|
||||||
|
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
|
|
||||||
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
|
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
|
||||||
multiple network interfaces
|
multiple network interfaces
|
||||||
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
|
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
|
||||||
* IGMP (Internet Group Management Protocol) for multicast traffic management
|
* IGMP (Internet Group Management Protocol) for multicast traffic management
|
||||||
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
|
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
|
||||||
RFC 2710. No support for MLDv2
|
RFC 2710. No support for MLDv2
|
||||||
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
|
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
|
||||||
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
||||||
(Address autoconfiguration)
|
(Address autoconfiguration)
|
||||||
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
|
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
|
||||||
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
|
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
|
||||||
and fast recovery/fast retransmit
|
and fast recovery/fast retransmit
|
||||||
* raw/native API for enhanced performance
|
* raw/native API for enhanced performance
|
||||||
* Optional Berkeley-like socket API
|
* Optional Berkeley-like socket API
|
||||||
* DNS (Domain names resolver)
|
* DNS (Domain names resolver)
|
||||||
|
|
||||||
|
|
||||||
APPLICATIONS
|
APPLICATIONS
|
||||||
|
|
||||||
* HTTP server with SSI and CGI
|
* HTTP server with SSI and CGI
|
||||||
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol)
|
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol)
|
||||||
* SNTP (Simple network time protocol)
|
* SNTP (Simple network time protocol)
|
||||||
|
* NetBIOS name service responder
|
||||||
|
* MDNS (Multicast DNS) responder
|
||||||
LICENSE
|
* iPerf server implementation
|
||||||
|
|
||||||
lwIP is freely available under a BSD license.
|
|
||||||
|
LICENSE
|
||||||
|
|
||||||
DEVELOPMENT
|
lwIP is freely available under a BSD license.
|
||||||
|
|
||||||
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
|
||||||
and developers using the stack often submit bug fixes, improvements,
|
DEVELOPMENT
|
||||||
and additions to the stack to further increase its usefulness.
|
|
||||||
|
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
||||||
Development of lwIP is hosted on Savannah, a central point for
|
and developers using the stack often submit bug fixes, improvements,
|
||||||
software development, maintenance and distribution. Everyone can
|
and additions to the stack to further increase its usefulness.
|
||||||
help improve lwIP by use of Savannah's interface, Git and the
|
|
||||||
mailing list. A core team of developers will commit changes to the
|
Development of lwIP is hosted on Savannah, a central point for
|
||||||
Git source tree.
|
software development, maintenance and distribution. Everyone can
|
||||||
|
help improve lwIP by use of Savannah's interface, Git and the
|
||||||
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
|
mailing list. A core team of developers will commit changes to the
|
||||||
contributions (such as platform ports) are in the 'contrib' Git module.
|
Git source tree.
|
||||||
|
|
||||||
See doc/savannah.txt for details on Git server access for users and
|
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
|
||||||
developers.
|
contributions (such as platform ports) are in the 'contrib' Git module.
|
||||||
|
|
||||||
The current Git trees are web-browsable:
|
See doc/savannah.txt for details on Git server access for users and
|
||||||
http://git.savannah.gnu.org/cgit/lwip.git
|
developers.
|
||||||
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
|
|
||||||
|
The current Git trees are web-browsable:
|
||||||
Submit patches and bugs via the lwIP project page:
|
http://git.savannah.gnu.org/cgit/lwip.git
|
||||||
http://savannah.nongnu.org/projects/lwip/
|
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
|
||||||
|
|
||||||
Continuous integration builds (GCC, clang):
|
Submit patches and bugs via the lwIP project page:
|
||||||
https://travis-ci.org/yarrick/lwip-merged
|
http://savannah.nongnu.org/projects/lwip/
|
||||||
|
|
||||||
|
Continuous integration builds (GCC, clang):
|
||||||
DOCUMENTATION
|
https://travis-ci.org/yarrick/lwip-merged
|
||||||
|
|
||||||
Self documentation of the source code is regularly extracted from the current
|
|
||||||
Git sources and is available from this web page:
|
DOCUMENTATION
|
||||||
http://www.nongnu.org/lwip/
|
|
||||||
|
Self documentation of the source code is regularly extracted from the current
|
||||||
There is now a constantly growin wiki about lwIP at
|
Git sources and is available from this web page:
|
||||||
http://lwip.wikia.com/wiki/LwIP_Wiki
|
http://www.nongnu.org/lwip/
|
||||||
|
|
||||||
Also, there are mailing lists you can subscribe at
|
There is now a constantly growing wiki about lwIP at
|
||||||
http://savannah.nongnu.org/mail/?group=lwip
|
http://lwip.wikia.com/wiki/LwIP_Wiki
|
||||||
plus searchable archives:
|
|
||||||
http://lists.nongnu.org/archive/html/lwip-users/
|
Also, there are mailing lists you can subscribe at
|
||||||
http://lists.nongnu.org/archive/html/lwip-devel/
|
http://savannah.nongnu.org/mail/?group=lwip
|
||||||
|
plus searchable archives:
|
||||||
lwIP was originally written by Adam Dunkels:
|
http://lists.nongnu.org/archive/html/lwip-users/
|
||||||
http://dunkels.com/adam/
|
http://lists.nongnu.org/archive/html/lwip-devel/
|
||||||
|
|
||||||
Reading Adam's papers, the files in docs/, browsing the source code
|
lwIP was originally written by Adam Dunkels:
|
||||||
documentation and browsing the mailing list archives is a good way to
|
http://dunkels.com/adam/
|
||||||
become familiar with the design of lwIP.
|
|
||||||
|
Reading Adam's papers, the files in docs/, browsing the source code
|
||||||
Adam Dunkels <adam@sics.se>
|
documentation and browsing the mailing list archives is a good way to
|
||||||
Leon Woestenberg <leon.woestenberg@gmx.net>
|
become familiar with the design of lwIP.
|
||||||
|
|
||||||
|
Adam Dunkels <adam@sics.se>
|
||||||
|
Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
|||||||
452
ext/lwip/UPGRADING
Normal file → Executable file
452
ext/lwip/UPGRADING
Normal file → Executable file
@@ -1,217 +1,235 @@
|
|||||||
This file lists major changes between release versions that require
|
This file lists major changes between release versions that require
|
||||||
ports or applications to be changed. Use it to update a port or an
|
ports or applications to be changed. Use it to update a port or an
|
||||||
application written for an older version of lwIP to correctly work
|
application written for an older version of lwIP to correctly work
|
||||||
with newer versions.
|
with newer versions.
|
||||||
|
|
||||||
|
|
||||||
(git master)
|
(git master)
|
||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
* TODO
|
(2.0.1)
|
||||||
|
|
||||||
(2.0.0)
|
++ Application changes:
|
||||||
|
|
||||||
++ 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
|
||||||
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
|
ip_current_netif() to the desired netif for every packet.
|
||||||
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
|
See bug #49662 for an explanation.
|
||||||
has to be set "up" before starting the DHCP client
|
|
||||||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
(2.0.0)
|
||||||
* 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);
|
++ Application changes:
|
||||||
supports SNMP2vc (experimental v3 support)
|
|
||||||
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
|
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
|
||||||
|
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
|
||||||
+++ Raw API:
|
has to be set "up" before starting the DHCP client
|
||||||
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
|
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||||
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
|
* 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);
|
||||||
+++ Socket API:
|
supports SNMPv2c (experimental v3 support)
|
||||||
* Added an implementation for posix sendmsg()
|
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
|
||||||
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
|
|
||||||
|
+++ Raw API:
|
||||||
++ Port changes
|
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
|
||||||
|
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
|
||||||
+++ new files:
|
|
||||||
* MANY new and moved files!
|
+++ Socket API:
|
||||||
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
|
* Added an implementation for posix sendmsg()
|
||||||
to let abc.h only contain the actual application programmer's API
|
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
|
||||||
|
|
||||||
+++ sys layer:
|
++ Port changes
|
||||||
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
|
|
||||||
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
|
+++ new files:
|
||||||
open to priority inversion, so this is not recommended any more)
|
* MANY new and moved files!
|
||||||
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
|
* Added src/Filelists.mk for use in Makefile projects
|
||||||
instead of using one per netconn (these semaphores are used even with core locking
|
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
|
||||||
enabled as some longer lasting functions like big writes still need to delay)
|
to let abc.h only contain the actual application programmer's API
|
||||||
|
|
||||||
+++ new options:
|
+++ sys layer:
|
||||||
* TODO
|
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
|
||||||
|
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
|
||||||
+++ new pools:
|
open to priority inversion, so this is not recommended any more)
|
||||||
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
|
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
|
||||||
that share memp.c code but do not have to be made global via lwippools.h
|
instead of using one per netconn (these semaphores are used even with core locking
|
||||||
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
|
enabled as some longer lasting functions like big writes still need to delay)
|
||||||
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
|
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
|
||||||
is now available
|
in def.h (to be overridden in cc.h) instead of config
|
||||||
|
options for netbiosns, httpd, dns, etc. ...
|
||||||
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
|
* New abstraction for hton* and ntoh* functions in def.h.
|
||||||
or to move buffers to dedicated memory using compiler attributes
|
To override them, use the following in cc.h:
|
||||||
|
#define lwip_htons(x) <your_htons>
|
||||||
* Standard C headers are used to define sized types and printf formatters
|
#define lwip_htonl(x) <your_htonl>
|
||||||
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
|
|
||||||
does not support these)
|
+++ new options:
|
||||||
|
* TODO
|
||||||
|
|
||||||
++ Major bugfixes/improvements
|
+++ new pools:
|
||||||
|
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
|
||||||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
that share memp.c code but do not have to be made global via lwippools.h
|
||||||
* Major rewrite of PPP (incl. keep-up with apache pppd)
|
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
|
||||||
* Major rewrite of SNMP (incl. MIB parser)
|
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
|
||||||
* Fixed timing issues that might have lead to losing a DHCP lease
|
is now available
|
||||||
* Made rx processing path more robust against crafted errors
|
|
||||||
* TCP window scaling support
|
* Signature of LWIP_HOOK_VLAN_SET macro was changed
|
||||||
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
|
|
||||||
* made DNS client more robust
|
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
|
||||||
* support PBUF_REF for RX packets
|
or to move buffers to dedicated memory using compiler attributes
|
||||||
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
|
|
||||||
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
|
* Standard C headers are used to define sized types and printf formatters
|
||||||
* Moved and reorderd stats (mainly memp/mib2)
|
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
|
||||||
|
does not support these)
|
||||||
(1.4.0)
|
|
||||||
|
|
||||||
++ Application changes:
|
++ Major bugfixes/improvements
|
||||||
|
|
||||||
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
|
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||||
compatibility to old applications, but will be removed in the future).
|
* Major rewrite of PPP (incl. keep-up with apache pppd)
|
||||||
|
see doc/ppp.txt for an upgrading how-to
|
||||||
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
|
* Major rewrite of SNMP (incl. MIB parser)
|
||||||
|
* Fixed timing issues that might have lead to losing a DHCP lease
|
||||||
+++ Raw API:
|
* Made rx processing path more robust against crafted errors
|
||||||
* Changed the semantics of tcp_close() (since it was rather a
|
* TCP window scaling support
|
||||||
shutdown before): Now the application does *NOT* get any calls to the recv
|
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
|
||||||
callback (aside from NULL/closed) after calling tcp_close()
|
* made DNS client more robust
|
||||||
|
* support PBUF_REF for RX packets
|
||||||
* When calling tcp_abort() from a raw API TCP callback function,
|
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
|
||||||
make sure you return ERR_ABRT to prevent accessing unallocated memory.
|
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
|
||||||
(ERR_ABRT now means the applicaiton has called tcp_abort!)
|
* Moved and reordered stats (mainly memp/mib2)
|
||||||
|
|
||||||
+++ Netconn API:
|
(1.4.0)
|
||||||
* Changed netconn_receive() and netconn_accept() to return
|
|
||||||
err_t, not a pointer to new data/netconn.
|
++ Application changes:
|
||||||
|
|
||||||
+++ Socket API:
|
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
|
||||||
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
|
compatibility to old applications, but will be removed in the future).
|
||||||
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
|
|
||||||
|
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||||
* Added a minimal version of posix fctl() to have a
|
|
||||||
standardised way to set O_NONBLOCK for nonblocking sockets.
|
+++ Raw API:
|
||||||
|
* Changed the semantics of tcp_close() (since it was rather a
|
||||||
+++ all APIs:
|
shutdown before): Now the application does *NOT* get any calls to the recv
|
||||||
* correctly implemented SO(F)_REUSEADDR
|
callback (aside from NULL/closed) after calling tcp_close()
|
||||||
|
|
||||||
++ Port changes
|
* When calling tcp_abort() from a raw API TCP callback function,
|
||||||
|
make sure you return ERR_ABRT to prevent accessing unallocated memory.
|
||||||
+++ new files:
|
(ERR_ABRT now means the applicaiton has called tcp_abort!)
|
||||||
|
|
||||||
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
|
+++ Netconn API:
|
||||||
|
* Changed netconn_receive() and netconn_accept() to return
|
||||||
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
|
err_t, not a pointer to new data/netconn.
|
||||||
the actual application programmer's API
|
|
||||||
|
+++ Socket API:
|
||||||
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
|
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
|
||||||
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
|
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
|
||||||
still want to use your own timer implementation for NO_SYS==0 (as before).
|
|
||||||
|
* Added a minimal version of posix fctl() to have a
|
||||||
+++ sys layer:
|
standardised way to set O_NONBLOCK for nonblocking sockets.
|
||||||
|
|
||||||
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
|
+++ all APIs:
|
||||||
sys_sem_t;
|
* correctly implemented SO(F)_REUSEADDR
|
||||||
|
|
||||||
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
|
++ Port changes
|
||||||
|
|
||||||
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
|
+++ new files:
|
||||||
binary semaphores instead of mutexes - as before)
|
|
||||||
|
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
|
||||||
+++ new options:
|
|
||||||
|
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
|
||||||
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
|
the actual application programmer's API
|
||||||
prevent creating many small pbufs when calling tcp_write with many small
|
|
||||||
blocks of data. Instead, pbufs are allocated larger than needed and the
|
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
|
||||||
space is used for later calls to tcp_write.
|
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
|
||||||
|
still want to use your own timer implementation for NO_SYS==0 (as before).
|
||||||
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
|
|
||||||
in tcp_write/udp_send.
|
+++ sys layer:
|
||||||
|
|
||||||
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
|
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
|
||||||
(necessary for pure PPPoE)
|
sys_sem_t;
|
||||||
|
|
||||||
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
|
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
|
||||||
be used to place these pools into user-defined memory by using external
|
|
||||||
declaration.
|
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
|
||||||
|
binary semaphores instead of mutexes - as before)
|
||||||
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
|
|
||||||
|
+++ new options:
|
||||||
+++ new pools:
|
|
||||||
|
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
|
||||||
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
|
prevent creating many small pbufs when calling tcp_write with many small
|
||||||
so MEMP_NUM_NETDB has to be set accordingly.
|
blocks of data. Instead, pbufs are allocated larger than needed and the
|
||||||
|
space is used for later calls to tcp_write.
|
||||||
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
|
|
||||||
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
|
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
|
||||||
|
in tcp_write/udp_send.
|
||||||
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
|
|
||||||
to be set accordingly.
|
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
|
||||||
|
(necessary for pure PPPoE)
|
||||||
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
|
|
||||||
has to be set accordingly
|
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
|
||||||
|
be used to place these pools into user-defined memory by using external
|
||||||
* Integrated loopif into netif.c - loopif does not have to be created by the
|
declaration.
|
||||||
port any more, just define LWIP_HAVE_LOOPIF to 1.
|
|
||||||
|
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
|
||||||
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
|
|
||||||
in cc.h, e.g. used by igmp)
|
+++ new pools:
|
||||||
|
|
||||||
* Added printf-formatter X8_F to printf u8_t as hex
|
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
|
||||||
|
so MEMP_NUM_NETDB has to be set accordingly.
|
||||||
* The heap now may be moved to user-defined memory by defining
|
|
||||||
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
|
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
|
||||||
|
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
|
||||||
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
|
|
||||||
with user-allocated structs instead of calling mem_malloc
|
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
|
||||||
|
to be set accordingly.
|
||||||
* Added const char* name to mem- and memp-stats for easier debugging.
|
|
||||||
|
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
|
||||||
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
has to be set accordingly
|
||||||
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
|
||||||
|
* Integrated loopif into netif.c - loopif does not have to be created by the
|
||||||
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
port any more, just define LWIP_HAVE_LOOPIF to 1.
|
||||||
more than one pcb.
|
|
||||||
|
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
|
||||||
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
|
in cc.h, e.g. used by igmp)
|
||||||
off any more, if this is set to 0, only one packet (the most recent one) is
|
|
||||||
queued (like demanded by RFC 1122).
|
* Added printf-formatter X8_F to printf u8_t as hex
|
||||||
|
|
||||||
|
* The heap now may be moved to user-defined memory by defining
|
||||||
++ Major bugfixes/improvements
|
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
|
||||||
|
|
||||||
* Implemented tcp_shutdown() to only shut down one end of a connection
|
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
|
||||||
* Implemented shutdown() at socket- and netconn-level
|
with user-allocated structs instead of calling mem_malloc
|
||||||
* Added errorset support to select() + improved select speed overhead
|
|
||||||
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
|
* Added const char* name to mem- and memp-stats for easier debugging.
|
||||||
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
|
|
||||||
* Use macros defined in ip_addr.h to work with IP addresses
|
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
||||||
* Implemented many nonblocking socket/netconn functions
|
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
||||||
* Fixed ARP input processing: only add a new entry if a request was directed as us
|
|
||||||
* mem_realloc() to mem_trim() to prevent confusion with realloc()
|
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
||||||
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
|
more than one pcb.
|
||||||
existing connections when assigning a routable address)
|
|
||||||
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
|
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
|
||||||
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
|
off any more, if this is set to 0, only one packet (the most recent one) is
|
||||||
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
|
queued (like demanded by RFC 1122).
|
||||||
* Added support for static ARP table entries
|
|
||||||
|
|
||||||
(STABLE-1.3.2)
|
++ Major bugfixes/improvements
|
||||||
|
|
||||||
* initial version of this file
|
* Implemented tcp_shutdown() to only shut down one end of a connection
|
||||||
|
* Implemented shutdown() at socket- and netconn-level
|
||||||
|
* Added errorset support to select() + improved select speed overhead
|
||||||
|
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
|
||||||
|
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
|
||||||
|
* Use macros defined in ip_addr.h to work with IP addresses
|
||||||
|
* Implemented many nonblocking socket/netconn functions
|
||||||
|
* Fixed ARP input processing: only add a new entry if a request was directed as us
|
||||||
|
* mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||||
|
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
|
||||||
|
existing connections when assigning a routable address)
|
||||||
|
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
|
||||||
|
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
|
||||||
|
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
|
||||||
|
* Added support for static ARP table entries
|
||||||
|
|
||||||
|
(STABLE-1.3.2)
|
||||||
|
|
||||||
|
* initial version of this file
|
||||||
|
|||||||
15
ext/lwip/doc/FILES
Normal file → Executable file
15
ext/lwip/doc/FILES
Normal file → Executable file
@@ -1,6 +1,9 @@
|
|||||||
savannah.txt - How to obtain the current development source code.
|
doxygen/ - Configuration files and scripts to create the lwIP doxygen source
|
||||||
contrib.txt - How to contribute to lwIP as a developer.
|
documentation (found at http://www.nongnu.org/lwip/)
|
||||||
rawapi.txt - The documentation for the core API of lwIP.
|
|
||||||
Also provides an overview about the other APIs and multithreading.
|
savannah.txt - How to obtain the current development source code.
|
||||||
snmp_agent.txt - The documentation for the lwIP SNMP agent.
|
contrib.txt - How to contribute to lwIP as a developer.
|
||||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
rawapi.txt - The documentation for the core API of lwIP.
|
||||||
|
Also provides an overview about the other APIs and multithreading.
|
||||||
|
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||||
|
ppp.txt - Documentation of the PPP interface for lwIP.
|
||||||
|
|||||||
117
ext/lwip/doc/NO_SYS_SampleCode.c
Executable file
117
ext/lwip/doc/NO_SYS_SampleCode.c
Executable file
@@ -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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
116
ext/lwip/doc/contrib.txt
Normal file → Executable file
116
ext/lwip/doc/contrib.txt
Normal file → Executable file
@@ -1,58 +1,58 @@
|
|||||||
1 Introduction
|
1 Introduction
|
||||||
|
|
||||||
This document describes some guidelines for people participating
|
This document describes some guidelines for people participating
|
||||||
in lwIP development.
|
in lwIP development.
|
||||||
|
|
||||||
2 How to contribute to lwIP
|
2 How to contribute to lwIP
|
||||||
|
|
||||||
Here is a short list of suggestions to anybody working with lwIP and
|
Here is a short list of suggestions to anybody working with lwIP and
|
||||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||||
First of all as you may already know lwIP is a volunteer project so feedback
|
First of all as you may already know lwIP is a volunteer project so feedback
|
||||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||||
features of Savannah help us not lose users' input.
|
features of Savannah help us not lose users' input.
|
||||||
|
|
||||||
2.1 Source code style:
|
2.1 Source code style:
|
||||||
|
|
||||||
1. do not use tabs.
|
1. do not use tabs.
|
||||||
2. indentation is two spaces per level (i.e. per tab).
|
2. indentation is two spaces per level (i.e. per tab).
|
||||||
3. end debug messages with a trailing newline (\n).
|
3. end debug messages with a trailing newline (\n).
|
||||||
4. one space between keyword and opening bracket.
|
4. one space between keyword and opening bracket.
|
||||||
5. no space between function and opening bracket.
|
5. no space between function and opening bracket.
|
||||||
6. one space and no newline before opening curly braces of a block.
|
6. one space and no newline before opening curly braces of a block.
|
||||||
7. closing curly brace on a single line.
|
7. closing curly brace on a single line.
|
||||||
8. spaces surrounding assignment and comparisons.
|
8. spaces surrounding assignment and comparisons.
|
||||||
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
|
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
|
||||||
10. use current source code style as further reference.
|
10. use current source code style as further reference.
|
||||||
|
|
||||||
2.2 Source code documentation style:
|
2.2 Source code documentation style:
|
||||||
|
|
||||||
1. JavaDoc compliant and Doxygen compatible.
|
1. JavaDoc compliant and Doxygen compatible.
|
||||||
2. Function documentation above functions in .c files, not .h files.
|
2. Function documentation above functions in .c files, not .h files.
|
||||||
(This forces you to synchronize documentation and implementation.)
|
(This forces you to synchronize documentation and implementation.)
|
||||||
3. Use current documentation style as further reference.
|
3. Use current documentation style as further reference.
|
||||||
|
|
||||||
2.3 Bug reports and patches:
|
2.3 Bug reports and patches:
|
||||||
|
|
||||||
1. Make sure you are reporting bugs or send patches against the latest
|
1. Make sure you are reporting bugs or send patches against the latest
|
||||||
sources. (From the latest release and/or the current Git sources.)
|
sources. (From the latest release and/or the current Git sources.)
|
||||||
2. If you think you found a bug make sure it's not already filed in the
|
2. If you think you found a bug make sure it's not already filed in the
|
||||||
bugtracker at Savannah.
|
bugtracker at Savannah.
|
||||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
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
|
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.
|
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
|
This is a good way to see if they are used at all - the same goes for unix
|
||||||
netifs except tapif.
|
netifs except tapif.
|
||||||
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
||||||
or a patch will be enough.
|
or a patch will be enough.
|
||||||
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
||||||
5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other
|
5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other
|
||||||
trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you
|
trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you
|
||||||
change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than
|
change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than
|
||||||
if it's not to the point and long :) so the chances for it to be applied are greater.
|
if it's not to the point and long :) so the chances for it to be applied are greater.
|
||||||
|
|
||||||
2.4 Platform porters:
|
2.4 Platform porters:
|
||||||
|
|
||||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||||
can also ask for Git access to submit and maintain your port in the contrib Git module.
|
can also ask for Git access to submit and maintain your port in the contrib Git module.
|
||||||
|
|||||||
2
ext/lwip/doc/doxygen/generate.bat
Normal file → Executable file
2
ext/lwip/doc/doxygen/generate.bat
Normal file → Executable file
@@ -1 +1 @@
|
|||||||
doxygen lwip.Doxyfile
|
doxygen lwip.Doxyfile
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
doxygen lwip.Doxyfile
|
#!/bin/sh
|
||||||
|
|
||||||
|
doxygen lwip.Doxyfile
|
||||||
|
|||||||
164
ext/lwip/doc/doxygen/main_page.h
Normal file → Executable file
164
ext/lwip/doc/doxygen/main_page.h
Normal file → Executable file
@@ -1,32 +1,132 @@
|
|||||||
/**
|
/**
|
||||||
* @defgroup lwip lwIP
|
* @defgroup lwip lwIP
|
||||||
*
|
*
|
||||||
* @defgroup infrastructure Infrastructure
|
* @defgroup infrastructure Infrastructure
|
||||||
*
|
*
|
||||||
* @defgroup callbackstyle_api Callback-style APIs
|
* @defgroup callbackstyle_api Callback-style APIs
|
||||||
* Non thread-safe APIs, callback style for maximum performance and minimum
|
* Non thread-safe APIs, callback style for maximum performance and minimum
|
||||||
* memory footprint.
|
* memory footprint.
|
||||||
*
|
*
|
||||||
* @defgroup threadsafe_api Thread-safe APIs
|
* @defgroup sequential_api Sequential-style APIs
|
||||||
* Thread-safe APIs, blocking functions. More overhead, but can be called
|
* Sequential-style APIs, blocking functions. More overhead, but can be called
|
||||||
* from any thread except TCPIP thread.
|
* from any thread except TCPIP thread.
|
||||||
*
|
*
|
||||||
* @defgroup addons Addons
|
* @defgroup addons Addons
|
||||||
*
|
*
|
||||||
* @defgroup apps Applications
|
* @defgroup apps Applications
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mainpage Overview
|
* @mainpage Overview
|
||||||
* @verbinclude "README"
|
* @verbinclude "README"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page upgrading Upgrading
|
* @page upgrading Upgrading
|
||||||
* @verbinclude "UPGRADING"
|
* @verbinclude "UPGRADING"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page contrib How to contribute to lwIP
|
* @page changelog Changelog
|
||||||
* @verbinclude "contrib.txt"
|
* @verbinclude "CHANGELOG"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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"
|
||||||
|
*/
|
||||||
|
|||||||
10
ext/lwip/doc/doxygen/output/index.html
Executable file
10
ext/lwip/doc/doxygen/output/index.html
Executable file
@@ -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>
|
||||||
113
ext/lwip/doc/mdns.txt
Executable file
113
ext/lwip/doc/mdns.txt
Executable file
@@ -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.
|
||||||
|
|
||||||
162
ext/lwip/doc/mqtt_client.txt
Executable file
162
ext/lwip/doc/mqtt_client.txt
Executable file
@@ -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)
|
||||||
1058
ext/lwip/doc/ppp.txt
Normal file → Executable file
1058
ext/lwip/doc/ppp.txt
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1005
ext/lwip/doc/rawapi.txt
Normal file → Executable file
1005
ext/lwip/doc/rawapi.txt
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
240
ext/lwip/doc/savannah.txt
Normal file → Executable file
240
ext/lwip/doc/savannah.txt
Normal file → Executable file
@@ -1,120 +1,120 @@
|
|||||||
Daily Use Guide for using Savannah for lwIP
|
Daily Use Guide for using Savannah for lwIP
|
||||||
|
|
||||||
Table of Contents:
|
Table of Contents:
|
||||||
|
|
||||||
1 - Obtaining lwIP from the Git repository
|
1 - Obtaining lwIP from the Git repository
|
||||||
2 - Committers/developers Git access using SSH
|
2 - Committers/developers Git access using SSH
|
||||||
3 - Merging a development branch to master branch
|
3 - Merging a development branch to master branch
|
||||||
4 - How to release lwIP
|
4 - How to release lwIP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1 Obtaining lwIP from the Git repository
|
1 Obtaining lwIP from the Git repository
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
To perform an anonymous Git clone of the master branch (this is where
|
To perform an anonymous Git clone of the master branch (this is where
|
||||||
bug fixes and incremental enhancements occur), do this:
|
bug fixes and incremental enhancements occur), do this:
|
||||||
git clone git://git.savannah.nongnu.org/lwip.git
|
git clone git://git.savannah.nongnu.org/lwip.git
|
||||||
|
|
||||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||||
git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||||
|
|
||||||
Or, obtain a specific (fixed) release as follows:
|
Or, obtain a specific (fixed) release as follows:
|
||||||
git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||||
|
|
||||||
|
|
||||||
2 Committers/developers Git access using SSH
|
2 Committers/developers Git access using SSH
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||||
As such, Git commits to the server occur through a SSH tunnel for project members.
|
As such, Git commits to the server occur through a SSH tunnel for project members.
|
||||||
To create a SSH2 key pair in UNIX-like environments, do this:
|
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||||
ssh-keygen -t dsa
|
ssh-keygen -t dsa
|
||||||
|
|
||||||
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||||
documentation and a graphic user interface. Use its key generator.
|
documentation and a graphic user interface. Use its key generator.
|
||||||
|
|
||||||
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
|
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
|
||||||
a while so that Savannah can update its configuration (This can take minutes).
|
a while so that Savannah can update its configuration (This can take minutes).
|
||||||
|
|
||||||
Try to login using SSH:
|
Try to login using SSH:
|
||||||
ssh -v your_login@git.sv.gnu.org
|
ssh -v your_login@git.sv.gnu.org
|
||||||
|
|
||||||
If it tells you:
|
If it tells you:
|
||||||
Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686
|
Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686
|
||||||
|
|
||||||
Interactive shell login is not possible for security reasons.
|
Interactive shell login is not possible for security reasons.
|
||||||
VCS commands are allowed.
|
VCS commands are allowed.
|
||||||
Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
|
Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
|
||||||
You tried to execute:
|
You tried to execute:
|
||||||
Sorry, you are not allowed to execute that command.
|
Sorry, you are not allowed to execute that command.
|
||||||
Shared connection to git.sv.gnu.org closed.
|
Shared connection to git.sv.gnu.org closed.
|
||||||
|
|
||||||
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||||
are allowed to use SSH for Git only. Now, you should be able to do this:
|
are allowed to use SSH for Git only. Now, you should be able to do this:
|
||||||
git clone your_login@git.sv.gnu.org:/srv/git/lwip.git
|
git clone your_login@git.sv.gnu.org:/srv/git/lwip.git
|
||||||
|
|
||||||
After which you can edit your local files with bug fixes or new features and
|
After which you can edit your local files with bug fixes or new features and
|
||||||
commit them. Make sure you know what you are doing when using Git to make
|
commit them. Make sure you know what you are doing when using Git to make
|
||||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||||
|
|
||||||
(If SSH asks about authenticity of the host, you can check the key
|
(If SSH asks about authenticity of the host, you can check the key
|
||||||
fingerprint against https://savannah.nongnu.org/git/?group=lwip
|
fingerprint against https://savannah.nongnu.org/git/?group=lwip
|
||||||
|
|
||||||
|
|
||||||
3 - Merging a development branch to master branch
|
3 - Merging a development branch to master branch
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
Merging is a straightforward process in Git. How to merge all changes in a
|
Merging is a straightforward process in Git. How to merge all changes in a
|
||||||
development branch since our last merge from main:
|
development branch since our last merge from main:
|
||||||
|
|
||||||
Checkout the master branch:
|
Checkout the master branch:
|
||||||
git checkout master
|
git checkout master
|
||||||
|
|
||||||
Merge the development branch to master:
|
Merge the development branch to master:
|
||||||
git merge your-development-branch
|
git merge your-development-branch
|
||||||
|
|
||||||
Resolve any conflict.
|
Resolve any conflict.
|
||||||
|
|
||||||
Commit the merge result.
|
Commit the merge result.
|
||||||
git commit -a
|
git commit -a
|
||||||
|
|
||||||
Push your commits:
|
Push your commits:
|
||||||
git push
|
git push
|
||||||
|
|
||||||
|
|
||||||
4 How to release lwIP
|
4 How to release lwIP
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
First, tag the release using Git: (I use release number 1.4.1 throughout
|
First, tag the release using Git: (I use release number 1.4.1 throughout
|
||||||
this example).
|
this example).
|
||||||
git tag -a STABLE-1_4_1
|
git tag -a STABLE-1_4_1
|
||||||
|
|
||||||
Share the tag reference by pushing it to remote:
|
Share the tag reference by pushing it to remote:
|
||||||
git push origin STABLE-1_4_1
|
git push origin STABLE-1_4_1
|
||||||
|
|
||||||
Prepare the release:
|
Prepare the release:
|
||||||
cp -r lwip lwip-1.4.1
|
cp -r lwip lwip-1.4.1
|
||||||
rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes
|
rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes
|
||||||
|
|
||||||
Archive the current directory using tar, gzip'd, bzip2'd and zip'd.
|
Archive the current directory using tar, gzip'd, bzip2'd and zip'd.
|
||||||
tar czvf lwip-1.4.1.tar.gz lwip-1.4.1
|
tar czvf lwip-1.4.1.tar.gz lwip-1.4.1
|
||||||
tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1
|
tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1
|
||||||
zip -r lwip-1.4.1.zip lwip-1.4.1
|
zip -r lwip-1.4.1.zip lwip-1.4.1
|
||||||
|
|
||||||
Now, sign the archives with a detached GPG binary signature as follows:
|
Now, sign the archives with a detached GPG binary signature as follows:
|
||||||
gpg -b lwip-1.4.1.tar.gz
|
gpg -b lwip-1.4.1.tar.gz
|
||||||
gpg -b lwip-1.4.1.tar.bz2
|
gpg -b lwip-1.4.1.tar.bz2
|
||||||
gpg -b lwip-1.4.1.zip
|
gpg -b lwip-1.4.1.zip
|
||||||
|
|
||||||
Upload these files using anonymous FTP:
|
Upload these files using anonymous FTP:
|
||||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||||
ncftp> mput *1.4.1.*
|
ncftp> mput *1.4.1.*
|
||||||
|
|
||||||
Additionally, you may post a news item on Savannah, like this:
|
Additionally, you may post a news item on Savannah, like this:
|
||||||
|
|
||||||
A new 1.4.1 release is now available here:
|
A new 1.4.1 release is now available here:
|
||||||
http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
|
http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
|
||||||
|
|
||||||
You will have to submit this via the user News interface, then approve
|
You will have to submit this via the user News interface, then approve
|
||||||
this via the Administrator News interface.
|
this via the Administrator News interface.
|
||||||
|
|||||||
570
ext/lwip/doc/sys_arch.txt
Normal file → Executable file
570
ext/lwip/doc/sys_arch.txt
Normal file → Executable file
@@ -1,267 +1,303 @@
|
|||||||
sys_arch interface for lwIP 0.6++
|
sys_arch interface for lwIP
|
||||||
|
|
||||||
Author: Adam Dunkels
|
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
|
The operating system emulation layer provides a common interface
|
||||||
general idea is that porting lwIP to new architectures requires only
|
between the lwIP code and the underlying operating system kernel. The
|
||||||
small changes to a few header files and a new sys_arch
|
general idea is that porting lwIP to new architectures requires only
|
||||||
implementation. It is also possible to do a sys_arch implementation
|
small changes to a few header files and a new sys_arch
|
||||||
that does not rely on any underlying operating system.
|
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
|
|
||||||
lwIP functionality, multiple threads support can be implemented in the
|
The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full
|
||||||
sys_arch, but this is not required for the basic lwIP
|
lwIP functionality, multiple threads support can be implemented in the
|
||||||
functionality. Previous versions of lwIP required the sys_arch to
|
sys_arch, but this is not required for the basic lwIP
|
||||||
implement timer scheduling as well but as of lwIP 0.5 this is
|
functionality. Timer scheduling is implemented in lwIP, but can be implemented
|
||||||
implemented in a higher layer.
|
by the sys_arch port (LWIP_TIMERS_CUSTOM==1).
|
||||||
|
|
||||||
In addition to the source file providing the functionality of sys_arch,
|
In addition to the source file providing the functionality of sys_arch,
|
||||||
the OS emulation layer must provide several header files defining
|
the OS emulation layer must provide several header files defining
|
||||||
macros used throughout lwip. The files required and the macros they
|
macros used throughout lwip. The files required and the macros they
|
||||||
must define are listed below the sys_arch description.
|
must define are listed below the sys_arch description.
|
||||||
|
|
||||||
Semaphores can be either counting or binary - lwIP works with both
|
Semaphores can be either counting or binary - lwIP works with both
|
||||||
kinds. Mailboxes are used for message passing and can be implemented
|
kinds. Mailboxes should be implemented as a queue which allows multiple messages
|
||||||
either as a queue which allows multiple messages to be posted to a
|
to be posted (implementing as a rendez-vous point where only one message can be
|
||||||
mailbox, or 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
|
||||||
posted at a time. lwIP works with both kinds, but the former type will
|
in a mailbox is just a pointer, nothing more.
|
||||||
be more efficient. 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
|
||||||
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t".
|
||||||
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
lwIP does not place any restrictions on how these types are represented
|
||||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
internally.
|
||||||
sys_sem_t or sys_mbox_t are represented internally.
|
|
||||||
|
Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that
|
||||||
Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that
|
allows both using pointers or actual OS structures to be used. This way, memory
|
||||||
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
|
||||||
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).
|
||||||
stack) or on the heap (allocated internally in the "*_new()" functions).
|
|
||||||
|
The following functions must be implemented by the sys_arch:
|
||||||
The following functions must be implemented by the sys_arch:
|
|
||||||
|
- void sys_init(void)
|
||||||
- void sys_init(void)
|
|
||||||
|
Is called to initialize the sys_arch layer.
|
||||||
Is called to initialize the sys_arch layer.
|
|
||||||
|
- err_t sys_sem_new(sys_sem_t *sem, u8_t count)
|
||||||
- err_t sys_sem_new(sys_sem_t *sem, u8_t count)
|
|
||||||
|
Creates a new semaphore. The semaphore is allocated to the memory that 'sem'
|
||||||
Creates a new semaphore. The semaphore is allocated to the memory that 'sem'
|
points to (which can be both a pointer or the actual OS structure).
|
||||||
points to (which can be both a pointer or the actual OS structure).
|
The "count" argument specifies the initial state of the semaphore (which is
|
||||||
The "count" argument specifies the initial state of the semaphore (which is
|
either 0 or 1).
|
||||||
either 0 or 1).
|
If the semaphore has been created, ERR_OK should be returned. Returning any
|
||||||
If the semaphore has been created, ERR_OK should be returned. Returning any
|
other error will provide a hint what went wrong, but except for assertions,
|
||||||
other error will provide a hint what went wrong, but except for assertions,
|
no real error handling is implemented.
|
||||||
no real error handling is implemented.
|
|
||||||
|
- void sys_sem_free(sys_sem_t *sem)
|
||||||
- void sys_sem_free(sys_sem_t *sem)
|
|
||||||
|
Deallocates a semaphore.
|
||||||
Deallocates a semaphore.
|
|
||||||
|
- void sys_sem_signal(sys_sem_t *sem)
|
||||||
- void sys_sem_signal(sys_sem_t *sem)
|
|
||||||
|
Signals a semaphore.
|
||||||
Signals a semaphore.
|
|
||||||
|
- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||||
- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
|
||||||
|
Blocks the thread while waiting for the semaphore to be
|
||||||
Blocks the thread while waiting for the semaphore to be
|
signaled. If the "timeout" argument is non-zero, the thread should
|
||||||
signaled. If the "timeout" argument is non-zero, the thread should
|
only be blocked for the specified time (measured in
|
||||||
only be blocked for the specified time (measured in
|
milliseconds). If the "timeout" argument is zero, the thread should be
|
||||||
milliseconds). If the "timeout" argument is zero, the thread should be
|
blocked until the semaphore is signalled.
|
||||||
blocked until the semaphore is signalled.
|
|
||||||
|
If the timeout argument is non-zero, the return value is the number of
|
||||||
If the timeout argument is non-zero, the return value is the number of
|
milliseconds spent waiting for the semaphore to be signaled. If the
|
||||||
milliseconds spent waiting for the semaphore to be signaled. If the
|
semaphore wasn't signaled within the specified time, the return value is
|
||||||
semaphore wasn't signaled within the specified time, the return value is
|
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
||||||
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
(i.e., it was already signaled), the function may return zero.
|
||||||
(i.e., it was already signaled), the function may return zero.
|
|
||||||
|
Notice that lwIP implements a function with a similar name,
|
||||||
Notice that lwIP implements a function with a similar name,
|
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
|
||||||
|
- int sys_sem_valid(sys_sem_t *sem)
|
||||||
- int sys_sem_valid(sys_sem_t *sem)
|
|
||||||
|
Returns 1 if the semaphore is valid, 0 if it is not valid.
|
||||||
Returns 1 if the semaphore is valid, 0 if it is not valid.
|
When using pointers, a simple way is to check the pointer for != NULL.
|
||||||
When using pointers, a simple way is to check the pointer for != NULL.
|
When directly using OS structures, implementing this may be more complex.
|
||||||
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.
|
||||||
This may also be a define, in which case the function is not prototyped.
|
|
||||||
|
- void sys_sem_set_invalid(sys_sem_t *sem)
|
||||||
- void sys_sem_set_invalid(sys_sem_t *sem)
|
|
||||||
|
Invalidate a semaphore so that sys_sem_valid() returns 0.
|
||||||
Invalidate a semaphore so that sys_sem_valid() returns 0.
|
ATTENTION: This does NOT mean that the semaphore shall be deallocated:
|
||||||
ATTENTION: This does NOT mean that the semaphore shall be deallocated:
|
sys_sem_free() is always called before calling this function!
|
||||||
sys_sem_free() is always called before calling this function!
|
This may also be a define, in which case the function is not prototyped.
|
||||||
This may also be a define, in which case the function is not prototyped.
|
|
||||||
|
- void sys_mutex_new(sys_mutex_t *mutex)
|
||||||
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
|
||||||
|
Creates a new mutex. The mutex is allocated to the memory that 'mutex'
|
||||||
Creates an empty mailbox for maximum "size" elements. Elements stored
|
points to (which can be both a pointer or the actual OS structure).
|
||||||
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
If the mutex has been created, ERR_OK should be returned. Returning any
|
||||||
in your lwipopts.h, or ignore this parameter in your implementation
|
other error will provide a hint what went wrong, but except for assertions,
|
||||||
and use a default size.
|
no real error handling is implemented.
|
||||||
If the mailbox has been created, ERR_OK should be returned. Returning any
|
|
||||||
other error will provide a hint what went wrong, but except for assertions,
|
- void sys_mutex_free(sys_mutex_t *mutex)
|
||||||
no real error handling is implemented.
|
|
||||||
|
Deallocates a mutex.
|
||||||
- void sys_mbox_free(sys_mbox_t *mbox)
|
|
||||||
|
- void sys_mutex_lock(sys_mutex_t *mutex)
|
||||||
Deallocates a mailbox. If there are messages still present in the
|
|
||||||
mailbox when the mailbox is deallocated, it is an indication of a
|
Blocks the thread until the mutex can be grabbed.
|
||||||
programming error in lwIP and the developer should be notified.
|
|
||||||
|
- void sys_mutex_unlock(sys_mutex_t *mutex)
|
||||||
- void sys_mbox_post(sys_mbox_t *mbox, void *msg)
|
|
||||||
|
Releases the mutex previously locked through 'sys_mutex_lock()'.
|
||||||
Posts the "msg" to the mailbox. This function have to block until
|
|
||||||
the "msg" is really posted.
|
- void sys_mutex_valid(sys_mutex_t *mutex)
|
||||||
|
|
||||||
- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
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.
|
||||||
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
|
When directly using OS structures, implementing this may be more complex.
|
||||||
is full, else, ERR_OK if the "msg" is posted.
|
This may also be a define, in which case the function is not prototyped.
|
||||||
|
|
||||||
- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
|
- void sys_mutex_set_invalid(sys_mutex_t *mutex)
|
||||||
|
|
||||||
Blocks the thread until a message arrives in the mailbox, but does
|
Invalidate a mutex so that sys_mutex_valid() returns 0.
|
||||||
not block the thread longer than "timeout" milliseconds (similar to
|
ATTENTION: This does NOT mean that the mutex shall be deallocated:
|
||||||
the sys_arch_sem_wait() function). If "timeout" is 0, the thread should
|
sys_mutex_free() is always called before calling this function!
|
||||||
be blocked until a message arrives. The "msg" argument is a result
|
This may also be a define, in which case the function is not prototyped.
|
||||||
parameter that is set by the function (i.e., by doing "*msg =
|
|
||||||
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||||
should be dropped.
|
|
||||||
|
Creates an empty mailbox for maximum "size" elements. Elements stored
|
||||||
The return values are the same as for the sys_arch_sem_wait() function:
|
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
||||||
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
in your lwipopts.h, or ignore this parameter in your implementation
|
||||||
timeout.
|
and use a default size.
|
||||||
|
If the mailbox has been created, ERR_OK should be returned. Returning any
|
||||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
other error will provide a hint what went wrong, but except for assertions,
|
||||||
implemented by lwIP.
|
no real error handling is implemented.
|
||||||
|
|
||||||
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
|
- void sys_mbox_free(sys_mbox_t *mbox)
|
||||||
|
|
||||||
This is similar to sys_arch_mbox_fetch, however if a message is not
|
Deallocates a mailbox. If there are messages still present in the
|
||||||
present in the mailbox, it immediately returns with the code
|
mailbox when the mailbox is deallocated, it is an indication of a
|
||||||
SYS_MBOX_EMPTY. On success 0 is returned.
|
programming error in lwIP and the developer should be notified.
|
||||||
|
|
||||||
To allow for efficient implementations, this can be defined as a
|
- void sys_mbox_post(sys_mbox_t *mbox, void *msg)
|
||||||
function-like macro in sys_arch.h instead of a normal function. For
|
|
||||||
example, a naive implementation could be:
|
Posts the "msg" to the mailbox. This function have to block until
|
||||||
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
the "msg" is really posted.
|
||||||
sys_arch_mbox_fetch(mbox,msg,1)
|
|
||||||
although this would introduce unnecessary delays.
|
- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
||||||
|
|
||||||
- int sys_mbox_valid(sys_mbox_t *mbox)
|
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
|
||||||
|
is full, else, ERR_OK if the "msg" is posted.
|
||||||
Returns 1 if the mailbox is valid, 0 if it is not valid.
|
|
||||||
When using pointers, a simple way is to check the pointer for != NULL.
|
- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
|
||||||
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.
|
Blocks the thread until a message arrives in the mailbox, but does
|
||||||
|
not block the thread longer than "timeout" milliseconds (similar to
|
||||||
- void sys_mbox_set_invalid(sys_mbox_t *mbox)
|
the sys_arch_sem_wait() function). If "timeout" is 0, the thread should
|
||||||
|
be blocked until a message arrives. The "msg" argument is a result
|
||||||
Invalidate a mailbox so that sys_mbox_valid() returns 0.
|
parameter that is set by the function (i.e., by doing "*msg =
|
||||||
ATTENTION: This does NOT mean that the mailbox shall be deallocated:
|
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
||||||
sys_mbox_free() is always called before calling this function!
|
should be dropped.
|
||||||
This may also be a define, in which case the function is not prototyped.
|
|
||||||
|
The return values are the same as for the sys_arch_sem_wait() function:
|
||||||
If threads are supported by the underlying operating system and if
|
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
||||||
such functionality is needed in lwIP, the following function will have
|
timeout.
|
||||||
to be implemented as well:
|
|
||||||
|
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||||
- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
|
implemented by lwIP.
|
||||||
|
|
||||||
Starts a new thread named "name" with priority "prio" that will begin its
|
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
|
||||||
execution in the function "thread()". The "arg" argument will be passed as an
|
|
||||||
argument to the thread() function. The stack size to used for this thread is
|
This is similar to sys_arch_mbox_fetch, however if a message is not
|
||||||
the "stacksize" parameter. The id of the new thread is returned. Both the id
|
present in the mailbox, it immediately returns with the code
|
||||||
and the priority are system dependent.
|
SYS_MBOX_EMPTY. On success 0 is returned.
|
||||||
|
|
||||||
- sys_prot_t sys_arch_protect(void)
|
To allow for efficient implementations, this can be defined as a
|
||||||
|
function-like macro in sys_arch.h instead of a normal function. For
|
||||||
This optional function does a "fast" critical region protection and returns
|
example, a naive implementation could be:
|
||||||
the previous protection level. This function is only called during very short
|
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
||||||
critical regions. An embedded system which supports ISR-based drivers might
|
sys_arch_mbox_fetch(mbox,msg,1)
|
||||||
want to implement this function by disabling interrupts. Task-based systems
|
although this would introduce unnecessary delays.
|
||||||
might want to implement this by using a mutex or disabling tasking. This
|
|
||||||
function should support recursive calls from the same task or interrupt. In
|
- int sys_mbox_valid(sys_mbox_t *mbox)
|
||||||
other words, sys_arch_protect() could be called while already protected. In
|
|
||||||
that case the return value indicates that it is already protected.
|
Returns 1 if the mailbox is valid, 0 if it is not valid.
|
||||||
|
When using pointers, a simple way is to check the pointer for != NULL.
|
||||||
sys_arch_protect() is only required if your port is supporting an operating
|
When directly using OS structures, implementing this may be more complex.
|
||||||
system.
|
This may also be a define, in which case the function is not prototyped.
|
||||||
|
|
||||||
- void sys_arch_unprotect(sys_prot_t pval)
|
- void sys_mbox_set_invalid(sys_mbox_t *mbox)
|
||||||
|
|
||||||
This optional function does a "fast" set of critical region protection to the
|
Invalidate a mailbox so that sys_mbox_valid() returns 0.
|
||||||
value specified by pval. See the documentation for sys_arch_protect() for
|
ATTENTION: This does NOT mean that the mailbox shall be deallocated:
|
||||||
more information. This function is only required if your port is supporting
|
sys_mbox_free() is always called before calling this function!
|
||||||
an operating system.
|
This may also be a define, in which case the function is not prototyped.
|
||||||
|
|
||||||
For some configurations, you also need:
|
If threads are supported by the underlying operating system and if
|
||||||
|
such functionality is needed in lwIP, the following function will have
|
||||||
- u32_t sys_now(void)
|
to be implemented as well:
|
||||||
|
|
||||||
This optional function returns the current time in milliseconds (don't care
|
- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
|
||||||
for wraparound, this is only used for time diffs).
|
|
||||||
Not implementing this function means you cannot use some modules (e.g. TCP
|
Starts a new thread named "name" with priority "prio" that will begin its
|
||||||
timestamps, internal timeouts for NO_SYS==1).
|
execution in the function "thread()". The "arg" argument will be passed as an
|
||||||
|
argument to the thread() function. The stack size to used for this thread is
|
||||||
|
the "stacksize" parameter. The id of the new thread is returned. Both the id
|
||||||
Note:
|
and the priority are system dependent.
|
||||||
|
|
||||||
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
When lwIP is used from more than one context (e.g. from multiple threads OR from
|
||||||
mem_malloc() you can run into a circular function call problem. In mem.c
|
main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled!
|
||||||
mem_init() tries to allcate a semaphore using mem_malloc, which of course
|
|
||||||
can't be performed when sys_arch uses mem_malloc.
|
- sys_prot_t sys_arch_protect(void)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
This optional function does a "fast" critical region protection and returns
|
||||||
Additional files required for the "OS support" emulation layer:
|
the previous protection level. This function is only called during very short
|
||||||
-------------------------------------------------------------------------------
|
critical regions. An embedded system which supports ISR-based drivers might
|
||||||
|
want to implement this function by disabling interrupts. Task-based systems
|
||||||
cc.h - Architecture environment, some compiler specific, some
|
might want to implement this by using a mutex or disabling tasking. This
|
||||||
environment specific (probably should move env stuff
|
function should support recursive calls from the same task or interrupt. In
|
||||||
to sys_arch.h.)
|
other words, sys_arch_protect() could be called while already protected. In
|
||||||
|
that case the return value indicates that it is already protected.
|
||||||
Typedefs for the types used by lwip -
|
|
||||||
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
|
sys_arch_protect() is only required if your port is supporting an operating
|
||||||
|
system.
|
||||||
Compiler hints for packing lwip's structures -
|
|
||||||
PACK_STRUCT_FIELD(x)
|
- void sys_arch_unprotect(sys_prot_t pval)
|
||||||
PACK_STRUCT_STRUCT
|
|
||||||
PACK_STRUCT_BEGIN
|
This optional function does a "fast" set of critical region protection to the
|
||||||
PACK_STRUCT_END
|
value specified by pval. See the documentation for sys_arch_protect() for
|
||||||
|
more information. This function is only required if your port is supporting
|
||||||
Platform specific diagnostic output -
|
an operating system.
|
||||||
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
|
|
||||||
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
|
For some configurations, you also need:
|
||||||
Portability defines for printf formatters:
|
|
||||||
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
|
- u32_t sys_now(void)
|
||||||
|
|
||||||
"lightweight" synchronization mechanisms -
|
This optional function returns the current time in milliseconds (don't care
|
||||||
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
|
for wraparound, this is only used for time diffs).
|
||||||
SYS_ARCH_PROTECT(x) - enter protection mode.
|
Not implementing this function means you cannot use some modules (e.g. TCP
|
||||||
SYS_ARCH_UNPROTECT(x) - leave protection mode.
|
timestamps, internal timeouts for NO_SYS==1).
|
||||||
|
|
||||||
If the compiler does not provide memset() this file must include a
|
|
||||||
definition of it, or include a file which defines it.
|
Note:
|
||||||
|
|
||||||
This file must either include a system-local <errno.h> which defines
|
Be careful with using mem_malloc() in sys_arch. When malloc() refers to
|
||||||
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
|
mem_malloc() you can run into a circular function call problem. In mem.c
|
||||||
to make lwip/arch.h define the codes which are used throughout.
|
mem_init() tries to allcate a semaphore using mem_malloc, which of course
|
||||||
|
can't be performed when sys_arch uses mem_malloc.
|
||||||
|
|
||||||
perf.h - Architecture specific performance measurement.
|
-------------------------------------------------------------------------------
|
||||||
Measurement calls made throughout lwip, these can be defined to nothing.
|
Additional files required for the "OS support" emulation layer:
|
||||||
PERF_START - start measuring something.
|
-------------------------------------------------------------------------------
|
||||||
PERF_STOP(x) - stop measuring something, and record the result.
|
|
||||||
|
cc.h - Architecture environment, some compiler specific, some
|
||||||
sys_arch.h - Tied to sys_arch.c
|
environment specific (probably should move env stuff
|
||||||
|
to sys_arch.h.)
|
||||||
Arch dependent types for the following objects:
|
|
||||||
sys_sem_t, sys_mbox_t, sys_thread_t,
|
Typedefs for the types used by lwip -
|
||||||
And, optionally:
|
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
|
||||||
sys_prot_t
|
|
||||||
|
Compiler hints for packing lwip's structures -
|
||||||
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
|
PACK_STRUCT_FIELD(x)
|
||||||
SYS_MBOX_NULL NULL
|
PACK_STRUCT_STRUCT
|
||||||
SYS_SEM_NULL NULL
|
PACK_STRUCT_BEGIN
|
||||||
|
PACK_STRUCT_END
|
||||||
|
|
||||||
|
Platform specific diagnostic output -
|
||||||
|
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
|
||||||
|
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
|
||||||
|
Portability defines for printf formatters:
|
||||||
|
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
|
||||||
|
|
||||||
|
"lightweight" synchronization mechanisms -
|
||||||
|
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
|
||||||
|
SYS_ARCH_PROTECT(x) - enter protection mode.
|
||||||
|
SYS_ARCH_UNPROTECT(x) - leave protection mode.
|
||||||
|
|
||||||
|
If the compiler does not provide memset() this file must include a
|
||||||
|
definition of it, or include a file which defines it.
|
||||||
|
|
||||||
|
This file must either include a system-local <errno.h> which defines
|
||||||
|
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
|
||||||
|
to make lwip/arch.h define the codes which are used throughout.
|
||||||
|
|
||||||
|
|
||||||
|
perf.h - Architecture specific performance measurement.
|
||||||
|
Measurement calls made throughout lwip, these can be defined to nothing.
|
||||||
|
PERF_START - start measuring something.
|
||||||
|
PERF_STOP(x) - stop measuring something, and record the result.
|
||||||
|
|
||||||
|
sys_arch.h - Tied to sys_arch.c
|
||||||
|
|
||||||
|
Arch dependent types for the following objects:
|
||||||
|
sys_sem_t, sys_mbox_t, sys_thread_t,
|
||||||
|
And, optionally:
|
||||||
|
sys_prot_t
|
||||||
|
|
||||||
|
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
|
||||||
|
SYS_MBOX_NULL NULL
|
||||||
|
SYS_SEM_NULL NULL
|
||||||
|
|||||||
28
ext/lwip/src/FILES
Normal file → Executable file
28
ext/lwip/src/FILES
Normal file → Executable file
@@ -1,13 +1,15 @@
|
|||||||
api/ - The code for the high-level wrapper API. Not needed if
|
api/ - The code for the high-level wrapper API. Not needed if
|
||||||
you use the lowel-level call-back/raw API.
|
you use the lowel-level call-back/raw API.
|
||||||
|
|
||||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
apps/ - Higher layer applications that are specifically programmed
|
||||||
memory and buffer management, and the low-level raw API.
|
with the lwIP low-level raw API.
|
||||||
|
|
||||||
include/ - lwIP include files.
|
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||||
|
memory and buffer management, and the low-level raw API.
|
||||||
netif/ - Generic network interface device drivers are kept here,
|
|
||||||
as well as the ARP module.
|
include/ - lwIP include files.
|
||||||
|
|
||||||
For more information on the various subdirectories, check the FILES
|
netif/ - Generic network interface device drivers are kept here.
|
||||||
file in each directory.
|
|
||||||
|
For more information on the various subdirectories, check the FILES
|
||||||
|
file in each directory.
|
||||||
|
|||||||
350
ext/lwip/src/Filelists.mk
Normal file → Executable file
350
ext/lwip/src/Filelists.mk
Normal file → Executable file
@@ -1,169 +1,181 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# 1. Redistributions of source code must retain the above copyright notice,
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# 3. The name of the author may not be used to endorse or promote products
|
# 3. The name of the author may not be used to endorse or promote products
|
||||||
# derived from this software without specific prior written permission.
|
# derived from this software without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
# 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
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
# OF SUCH DAMAGE.
|
# OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# This file is part of the lwIP TCP/IP stack.
|
# This file is part of the lwIP TCP/IP stack.
|
||||||
#
|
#
|
||||||
# Author: Adam Dunkels <adam@sics.se>
|
# Author: Adam Dunkels <adam@sics.se>
|
||||||
#
|
#
|
||||||
|
|
||||||
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
|
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
|
||||||
COREFILES=$(LWIPDIR)/core/init.c \
|
COREFILES=$(LWIPDIR)/core/init.c \
|
||||||
$(LWIPDIR)/core/def.c \
|
$(LWIPDIR)/core/def.c \
|
||||||
$(LWIPDIR)/core/dns.c \
|
$(LWIPDIR)/core/dns.c \
|
||||||
$(LWIPDIR)/core/inet_chksum.c \
|
$(LWIPDIR)/core/inet_chksum.c \
|
||||||
$(LWIPDIR)/core/ip.c \
|
$(LWIPDIR)/core/ip.c \
|
||||||
$(LWIPDIR)/core/mem.c \
|
$(LWIPDIR)/core/mem.c \
|
||||||
$(LWIPDIR)/core/memp.c \
|
$(LWIPDIR)/core/memp.c \
|
||||||
$(LWIPDIR)/core/netif.c \
|
$(LWIPDIR)/core/netif.c \
|
||||||
$(LWIPDIR)/core/pbuf.c \
|
$(LWIPDIR)/core/pbuf.c \
|
||||||
$(LWIPDIR)/core/raw.c \
|
$(LWIPDIR)/core/raw.c \
|
||||||
$(LWIPDIR)/core/stats.c \
|
$(LWIPDIR)/core/stats.c \
|
||||||
$(LWIPDIR)/core/sys.c \
|
$(LWIPDIR)/core/sys.c \
|
||||||
$(LWIPDIR)/core/tcp.c \
|
$(LWIPDIR)/core/tcp.c \
|
||||||
$(LWIPDIR)/core/tcp_in.c \
|
$(LWIPDIR)/core/tcp_in.c \
|
||||||
$(LWIPDIR)/core/tcp_out.c \
|
$(LWIPDIR)/core/tcp_out.c \
|
||||||
$(LWIPDIR)/core/timeouts.c \
|
$(LWIPDIR)/core/timeouts.c \
|
||||||
$(LWIPDIR)/core/udp.c
|
$(LWIPDIR)/core/udp.c
|
||||||
|
|
||||||
CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
|
CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
|
||||||
$(LWIPDIR)/core/ipv4/dhcp.c \
|
$(LWIPDIR)/core/ipv4/dhcp.c \
|
||||||
$(LWIPDIR)/core/ipv4/etharp.c \
|
$(LWIPDIR)/core/ipv4/etharp.c \
|
||||||
$(LWIPDIR)/core/ipv4/icmp.c \
|
$(LWIPDIR)/core/ipv4/icmp.c \
|
||||||
$(LWIPDIR)/core/ipv4/igmp.c \
|
$(LWIPDIR)/core/ipv4/igmp.c \
|
||||||
$(LWIPDIR)/core/ipv4/ip4_frag.c \
|
$(LWIPDIR)/core/ipv4/ip4_frag.c \
|
||||||
$(LWIPDIR)/core/ipv4/ip4.c \
|
$(LWIPDIR)/core/ipv4/ip4.c \
|
||||||
$(LWIPDIR)/core/ipv4/ip4_addr.c
|
$(LWIPDIR)/core/ipv4/ip4_addr.c
|
||||||
|
|
||||||
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
|
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
|
||||||
$(LWIPDIR)/core/ipv6/ethip6.c \
|
$(LWIPDIR)/core/ipv6/ethip6.c \
|
||||||
$(LWIPDIR)/core/ipv6/icmp6.c \
|
$(LWIPDIR)/core/ipv6/icmp6.c \
|
||||||
$(LWIPDIR)/core/ipv6/inet6.c \
|
$(LWIPDIR)/core/ipv6/inet6.c \
|
||||||
$(LWIPDIR)/core/ipv6/ip6.c \
|
$(LWIPDIR)/core/ipv6/ip6.c \
|
||||||
$(LWIPDIR)/core/ipv6/ip6_addr.c \
|
$(LWIPDIR)/core/ipv6/ip6_addr.c \
|
||||||
$(LWIPDIR)/core/ipv6/ip6_frag.c \
|
$(LWIPDIR)/core/ipv6/ip6_frag.c \
|
||||||
$(LWIPDIR)/core/ipv6/mld6.c \
|
$(LWIPDIR)/core/ipv6/mld6.c \
|
||||||
$(LWIPDIR)/core/ipv6/nd6.c
|
$(LWIPDIR)/core/ipv6/nd6.c
|
||||||
|
|
||||||
# APIFILES: The files which implement the sequential and socket APIs.
|
# APIFILES: The files which implement the sequential and socket APIs.
|
||||||
APIFILES=$(LWIPDIR)/api/api_lib.c \
|
APIFILES=$(LWIPDIR)/api/api_lib.c \
|
||||||
$(LWIPDIR)/api/api_msg.c \
|
$(LWIPDIR)/api/api_msg.c \
|
||||||
$(LWIPDIR)/api/err.c \
|
$(LWIPDIR)/api/err.c \
|
||||||
$(LWIPDIR)/api/netbuf.c \
|
$(LWIPDIR)/api/netbuf.c \
|
||||||
$(LWIPDIR)/api/netdb.c \
|
$(LWIPDIR)/api/netdb.c \
|
||||||
$(LWIPDIR)/api/netifapi.c \
|
$(LWIPDIR)/api/netifapi.c \
|
||||||
$(LWIPDIR)/api/sockets.c \
|
$(LWIPDIR)/api/sockets.c \
|
||||||
$(LWIPDIR)/api/tcpip.c
|
$(LWIPDIR)/api/tcpip.c
|
||||||
|
|
||||||
# NETIFFILES: Files implementing various generic network interface functions
|
# NETIFFILES: Files implementing various generic network interface functions
|
||||||
NETIFFILES=$(LWIPDIR)/netif/ethernet.c \
|
NETIFFILES=$(LWIPDIR)/netif/ethernet.c \
|
||||||
$(LWIPDIR)/netif/slipif.c
|
$(LWIPDIR)/netif/slipif.c
|
||||||
|
|
||||||
# SIXLOWPAN: 6LoWPAN
|
# SIXLOWPAN: 6LoWPAN
|
||||||
SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \
|
SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \
|
||||||
|
|
||||||
# PPPFILES: PPP
|
# PPPFILES: PPP
|
||||||
PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \
|
PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \
|
||||||
$(LWIPDIR)/netif/ppp/ccp.c \
|
$(LWIPDIR)/netif/ppp/ccp.c \
|
||||||
$(LWIPDIR)/netif/ppp/chap-md5.c \
|
$(LWIPDIR)/netif/ppp/chap-md5.c \
|
||||||
$(LWIPDIR)/netif/ppp/chap_ms.c \
|
$(LWIPDIR)/netif/ppp/chap_ms.c \
|
||||||
$(LWIPDIR)/netif/ppp/chap-new.c \
|
$(LWIPDIR)/netif/ppp/chap-new.c \
|
||||||
$(LWIPDIR)/netif/ppp/demand.c \
|
$(LWIPDIR)/netif/ppp/demand.c \
|
||||||
$(LWIPDIR)/netif/ppp/eap.c \
|
$(LWIPDIR)/netif/ppp/eap.c \
|
||||||
$(LWIPDIR)/netif/ppp/ecp.c \
|
$(LWIPDIR)/netif/ppp/ecp.c \
|
||||||
$(LWIPDIR)/netif/ppp/eui64.c \
|
$(LWIPDIR)/netif/ppp/eui64.c \
|
||||||
$(LWIPDIR)/netif/ppp/fsm.c \
|
$(LWIPDIR)/netif/ppp/fsm.c \
|
||||||
$(LWIPDIR)/netif/ppp/ipcp.c \
|
$(LWIPDIR)/netif/ppp/ipcp.c \
|
||||||
$(LWIPDIR)/netif/ppp/ipv6cp.c \
|
$(LWIPDIR)/netif/ppp/ipv6cp.c \
|
||||||
$(LWIPDIR)/netif/ppp/lcp.c \
|
$(LWIPDIR)/netif/ppp/lcp.c \
|
||||||
$(LWIPDIR)/netif/ppp/magic.c \
|
$(LWIPDIR)/netif/ppp/magic.c \
|
||||||
$(LWIPDIR)/netif/ppp/mppe.c \
|
$(LWIPDIR)/netif/ppp/mppe.c \
|
||||||
$(LWIPDIR)/netif/ppp/multilink.c \
|
$(LWIPDIR)/netif/ppp/multilink.c \
|
||||||
$(LWIPDIR)/netif/ppp/ppp.c \
|
$(LWIPDIR)/netif/ppp/ppp.c \
|
||||||
$(LWIPDIR)/netif/ppp/pppapi.c \
|
$(LWIPDIR)/netif/ppp/pppapi.c \
|
||||||
$(LWIPDIR)/netif/ppp/pppcrypt.c \
|
$(LWIPDIR)/netif/ppp/pppcrypt.c \
|
||||||
$(LWIPDIR)/netif/ppp/pppoe.c \
|
$(LWIPDIR)/netif/ppp/pppoe.c \
|
||||||
$(LWIPDIR)/netif/ppp/pppol2tp.c \
|
$(LWIPDIR)/netif/ppp/pppol2tp.c \
|
||||||
$(LWIPDIR)/netif/ppp/pppos.c \
|
$(LWIPDIR)/netif/ppp/pppos.c \
|
||||||
$(LWIPDIR)/netif/ppp/upap.c \
|
$(LWIPDIR)/netif/ppp/upap.c \
|
||||||
$(LWIPDIR)/netif/ppp/utils.c \
|
$(LWIPDIR)/netif/ppp/utils.c \
|
||||||
$(LWIPDIR)/netif/ppp/vj.c \
|
$(LWIPDIR)/netif/ppp/vj.c \
|
||||||
$(LWIPDIR)/netif/ppp/polarssl/arc4.c \
|
$(LWIPDIR)/netif/ppp/polarssl/arc4.c \
|
||||||
$(LWIPDIR)/netif/ppp/polarssl/des.c \
|
$(LWIPDIR)/netif/ppp/polarssl/des.c \
|
||||||
$(LWIPDIR)/netif/ppp/polarssl/md4.c \
|
$(LWIPDIR)/netif/ppp/polarssl/md4.c \
|
||||||
$(LWIPDIR)/netif/ppp/polarssl/md5.c \
|
$(LWIPDIR)/netif/ppp/polarssl/md5.c \
|
||||||
$(LWIPDIR)/netif/ppp/polarssl/sha1.c
|
$(LWIPDIR)/netif/ppp/polarssl/sha1.c
|
||||||
|
|
||||||
# LWIPNOAPPSFILES: All LWIP files without apps
|
# LWIPNOAPPSFILES: All LWIP files without apps
|
||||||
LWIPNOAPPSFILES=$(COREFILES) \
|
LWIPNOAPPSFILES=$(COREFILES) \
|
||||||
$(CORE4FILES) \
|
$(CORE4FILES) \
|
||||||
$(CORE6FILES) \
|
$(CORE6FILES) \
|
||||||
$(APIFILES) \
|
$(APIFILES) \
|
||||||
$(NETIFFILES) \
|
$(NETIFFILES) \
|
||||||
$(PPPFILES) \
|
$(PPPFILES) \
|
||||||
$(SIXLOWPAN)
|
$(SIXLOWPAN)
|
||||||
|
|
||||||
# SNMPFILES: SNMPv2c agent
|
# SNMPFILES: SNMPv2c agent
|
||||||
SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \
|
SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_core.c \
|
$(LWIPDIR)/apps/snmp/snmp_core.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_system.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_system.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \
|
$(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_msg.c \
|
$(LWIPDIR)/apps/snmp/snmp_msg.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmpv3.c \
|
$(LWIPDIR)/apps/snmp/snmpv3.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_netconn.c \
|
$(LWIPDIR)/apps/snmp/snmp_netconn.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \
|
$(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_raw.c \
|
$(LWIPDIR)/apps/snmp/snmp_raw.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_scalar.c \
|
$(LWIPDIR)/apps/snmp/snmp_scalar.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_table.c \
|
$(LWIPDIR)/apps/snmp/snmp_table.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_threadsync.c \
|
$(LWIPDIR)/apps/snmp/snmp_threadsync.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmp_traps.c \
|
$(LWIPDIR)/apps/snmp/snmp_traps.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \
|
$(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \
|
||||||
$(LWIPDIR)/apps/snmp/snmpv3_dummy.c
|
$(LWIPDIR)/apps/snmp/snmpv3_dummy.c
|
||||||
|
|
||||||
# HTTPDFILES: HTTP server
|
# HTTPDFILES: HTTP server
|
||||||
HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \
|
HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \
|
||||||
$(LWIPDIR)/apps/httpd/httpd.c
|
$(LWIPDIR)/apps/httpd/httpd.c
|
||||||
|
|
||||||
# LWIPERFFILES: IPERF server
|
# LWIPERFFILES: IPERF server
|
||||||
LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
|
LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
|
||||||
|
|
||||||
# SNTPFILES: SNTP client
|
# SNTPFILES: SNTP client
|
||||||
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
|
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
|
||||||
|
|
||||||
# NETBIOSNSFILES: NetBIOS name server
|
# MDNSFILES: MDNS responder
|
||||||
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
|
MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
|
||||||
|
|
||||||
# LWIPAPPFILES: All LWIP APPs
|
# NETBIOSNSFILES: NetBIOS name server
|
||||||
LWIPAPPFILES=$(SNMPFILES) \
|
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
|
||||||
$(HTTPDFILES) \
|
|
||||||
$(LWIPERFFILES) \
|
# TFTPFILES: TFTP server files
|
||||||
$(SNTPFILES) \
|
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
|
||||||
$(NETBIOSNSFILES)
|
|
||||||
|
# MQTTFILES: MQTT client files
|
||||||
|
MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c
|
||||||
|
|
||||||
|
# LWIPAPPFILES: All LWIP APPs
|
||||||
|
LWIPAPPFILES=$(SNMPFILES) \
|
||||||
|
$(HTTPDFILES) \
|
||||||
|
$(LWIPERFFILES) \
|
||||||
|
$(SNTPFILES) \
|
||||||
|
$(MDNSFILES) \
|
||||||
|
$(NETBIOSNSFILES) \
|
||||||
|
$(TFTPFILES) \
|
||||||
|
$(MQTTFILES)
|
||||||
|
|||||||
2003
ext/lwip/src/api/api_lib.c
Normal file → Executable file
2003
ext/lwip/src/api/api_lib.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
3893
ext/lwip/src/api/api_msg.c
Normal file → Executable file
3893
ext/lwip/src/api/api_msg.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
190
ext/lwip/src/api/err.c
Normal file → Executable file
190
ext/lwip/src/api/err.c
Normal file → Executable file
@@ -1,75 +1,115 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Error Management module
|
* Error Management module
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
#ifdef LWIP_DEBUG
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
static const char *err_strerr[] = {
|
#include <errno.h>
|
||||||
"Ok.", /* ERR_OK 0 */
|
|
||||||
"Out of memory error.", /* ERR_MEM -1 */
|
#if !NO_SYS
|
||||||
"Buffer error.", /* ERR_BUF -2 */
|
/** Table to quickly map an lwIP error (err_t) to a socket error
|
||||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
* by using -err as an index */
|
||||||
"Routing problem.", /* ERR_RTE -4 */
|
static const int err_to_errno_table[] = {
|
||||||
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
0, /* ERR_OK 0 No error, everything OK. */
|
||||||
"Illegal value.", /* ERR_VAL -6 */
|
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||||
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||||
"Address in use.", /* ERR_USE -8 */
|
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||||
"Already connecting.", /* ERR_ALREADY -9 */
|
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||||
"Already connected.", /* ERR_ISCONN -10 */
|
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||||
"Not connected.", /* ERR_CONN -11 */
|
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||||
"Low-level netif error.", /* ERR_IF -12 */
|
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||||
"Connection aborted.", /* ERR_ABRT -13 */
|
EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||||
"Connection reset.", /* ERR_RST -14 */
|
EALREADY, /* ERR_ALREADY -9 Already connecting. */
|
||||||
"Connection closed.", /* ERR_CLSD -15 */
|
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
|
||||||
"Illegal argument." /* ERR_ARG -16 */
|
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. */
|
||||||
* Convert an lwip internal error to a string representation.
|
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
|
||||||
*
|
EIO /* ERR_ARG -16 Illegal argument. */
|
||||||
* @param err an lwip internal err_t
|
};
|
||||||
* @return a string representation for err
|
|
||||||
*/
|
int
|
||||||
const char *
|
err_to_errno(err_t err)
|
||||||
lwip_strerr(err_t err)
|
{
|
||||||
{
|
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
|
||||||
return err_strerr[-err];
|
return EIO;
|
||||||
}
|
}
|
||||||
|
return err_to_errno_table[-err];
|
||||||
#endif /* LWIP_DEBUG */
|
}
|
||||||
|
#endif /* !NO_SYS */
|
||||||
|
|
||||||
|
#ifdef LWIP_DEBUG
|
||||||
|
|
||||||
|
static const char *err_strerr[] = {
|
||||||
|
"Ok.", /* ERR_OK 0 */
|
||||||
|
"Out of memory error.", /* ERR_MEM -1 */
|
||||||
|
"Buffer error.", /* ERR_BUF -2 */
|
||||||
|
"Timeout.", /* ERR_TIMEOUT -3 */
|
||||||
|
"Routing problem.", /* ERR_RTE -4 */
|
||||||
|
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
||||||
|
"Illegal value.", /* ERR_VAL -6 */
|
||||||
|
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
||||||
|
"Address in use.", /* ERR_USE -8 */
|
||||||
|
"Already connecting.", /* ERR_ALREADY -9 */
|
||||||
|
"Already connected.", /* ERR_ISCONN -10 */
|
||||||
|
"Not connected.", /* ERR_CONN -11 */
|
||||||
|
"Low-level netif error.", /* ERR_IF -12 */
|
||||||
|
"Connection aborted.", /* ERR_ABRT -13 */
|
||||||
|
"Connection reset.", /* ERR_RST -14 */
|
||||||
|
"Connection closed.", /* ERR_CLSD -15 */
|
||||||
|
"Illegal argument." /* ERR_ARG -16 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an lwip internal error to a string representation.
|
||||||
|
*
|
||||||
|
* @param err an lwip internal err_t
|
||||||
|
* @return a string representation for err
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
lwip_strerr(err_t err)
|
||||||
|
{
|
||||||
|
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) {
|
||||||
|
return "Unknown error.";
|
||||||
|
}
|
||||||
|
return err_strerr[-err];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_DEBUG */
|
||||||
|
|||||||
509
ext/lwip/src/api/netbuf.c
Normal file → Executable file
509
ext/lwip/src/api/netbuf.c
Normal file → Executable file
@@ -1,263 +1,246 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Network buffer management
|
* Network buffer management
|
||||||
*
|
*
|
||||||
*/
|
* @defgroup netbuf Network buffers
|
||||||
|
* @ingroup netconn
|
||||||
/*
|
* Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* to avoid copying data around.\n
|
||||||
* All rights reserved.
|
* Buffers must not be shared accross multiple threads, all functions except
|
||||||
*
|
* netbuf_new() and netbuf_delete() are not thread-safe.
|
||||||
* 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,
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* this list of conditions and the following disclaimer.
|
* All rights reserved.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
*
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* and/or other materials provided with the distribution.
|
* are permitted provided that the following conditions are met:
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
*
|
||||||
* derived from this software without specific prior written permission.
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
*
|
* this list of conditions and the following disclaimer.
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* and/or other materials provided with the distribution.
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* derived from this software without specific prior written permission.
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
*
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* OF SUCH DAMAGE.
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
*
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
*
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* 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.
|
||||||
* @defgroup netbuf Network buffers
|
*
|
||||||
* @ingroup netconn
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
* 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 */
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
#include "lwip/netbuf.h"
|
||||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
#include "lwip/memp.h"
|
||||||
|
|
||||||
#include "lwip/netbuf.h"
|
#include <string.h>
|
||||||
#include "lwip/memp.h"
|
|
||||||
|
/**
|
||||||
#include <string.h>
|
* @ingroup netbuf
|
||||||
|
* Create (allocate) and initialize a new netbuf.
|
||||||
/**
|
* The netbuf doesn't yet contain a packet buffer!
|
||||||
* @ingroup netbuf
|
*
|
||||||
* Create (allocate) and initialize a new netbuf.
|
* @return a pointer to a new netbuf
|
||||||
* The netbuf doesn't yet contain a packet buffer!
|
* NULL on lack of memory
|
||||||
*
|
*/
|
||||||
* @return a pointer to a new netbuf
|
struct
|
||||||
* NULL on lack of memory
|
netbuf *netbuf_new(void)
|
||||||
*/
|
{
|
||||||
struct
|
struct netbuf *buf;
|
||||||
netbuf *netbuf_new(void)
|
|
||||||
{
|
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
||||||
struct netbuf *buf;
|
if (buf != NULL) {
|
||||||
|
memset(buf, 0, sizeof(struct netbuf));
|
||||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
}
|
||||||
if (buf != NULL) {
|
return buf;
|
||||||
buf->p = NULL;
|
}
|
||||||
buf->ptr = NULL;
|
|
||||||
ip_addr_set_zero(&buf->addr);
|
/**
|
||||||
buf->port = 0;
|
* @ingroup netbuf
|
||||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
* Deallocate a netbuf allocated by netbuf_new().
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
*
|
||||||
buf->flags = 0;
|
* @param buf pointer to a netbuf allocated by netbuf_new()
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
*/
|
||||||
buf->toport_chksum = 0;
|
void
|
||||||
#if LWIP_NETBUF_RECVINFO
|
netbuf_delete(struct netbuf *buf)
|
||||||
ip_addr_set_zero(&buf->toaddr);
|
{
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
if (buf != NULL) {
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
if (buf->p != NULL) {
|
||||||
return buf;
|
pbuf_free(buf->p);
|
||||||
} else {
|
buf->p = buf->ptr = NULL;
|
||||||
return NULL;
|
}
|
||||||
}
|
memp_free(MEMP_NETBUF, buf);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @ingroup netbuf
|
/**
|
||||||
* Deallocate a netbuf allocated by netbuf_new().
|
* @ingroup netbuf
|
||||||
*
|
* Allocate memory for a packet buffer for a given netbuf.
|
||||||
* @param buf pointer to a netbuf allocated by netbuf_new()
|
*
|
||||||
*/
|
* @param buf the netbuf for which to allocate a packet buffer
|
||||||
void
|
* @param size the size of the packet buffer to allocate
|
||||||
netbuf_delete(struct netbuf *buf)
|
* @return pointer to the allocated memory
|
||||||
{
|
* NULL if no memory could be allocated
|
||||||
if (buf != NULL) {
|
*/
|
||||||
if (buf->p != NULL) {
|
void *
|
||||||
pbuf_free(buf->p);
|
netbuf_alloc(struct netbuf *buf, u16_t size)
|
||||||
buf->p = buf->ptr = NULL;
|
{
|
||||||
}
|
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
|
||||||
memp_free(MEMP_NETBUF, buf);
|
|
||||||
}
|
/* Deallocate any previously allocated memory. */
|
||||||
}
|
if (buf->p != NULL) {
|
||||||
|
pbuf_free(buf->p);
|
||||||
/**
|
}
|
||||||
* @ingroup netbuf
|
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
||||||
* Allocate memory for a packet buffer for a given netbuf.
|
if (buf->p == NULL) {
|
||||||
*
|
return NULL;
|
||||||
* @param buf the netbuf for which to allocate a packet buffer
|
}
|
||||||
* @param size the size of the packet buffer to allocate
|
LWIP_ASSERT("check that first pbuf can hold size",
|
||||||
* @return pointer to the allocated memory
|
(buf->p->len >= size));
|
||||||
* NULL if no memory could be allocated
|
buf->ptr = buf->p;
|
||||||
*/
|
return buf->p->payload;
|
||||||
void *
|
}
|
||||||
netbuf_alloc(struct netbuf *buf, u16_t size)
|
|
||||||
{
|
/**
|
||||||
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
|
* @ingroup netbuf
|
||||||
|
* Free the packet buffer included in a netbuf
|
||||||
/* Deallocate any previously allocated memory. */
|
*
|
||||||
if (buf->p != NULL) {
|
* @param buf pointer to the netbuf which contains the packet buffer to free
|
||||||
pbuf_free(buf->p);
|
*/
|
||||||
}
|
void
|
||||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
netbuf_free(struct netbuf *buf)
|
||||||
if (buf->p == NULL) {
|
{
|
||||||
return NULL;
|
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
||||||
}
|
if (buf->p != NULL) {
|
||||||
LWIP_ASSERT("check that first pbuf can hold size",
|
pbuf_free(buf->p);
|
||||||
(buf->p->len >= size));
|
}
|
||||||
buf->ptr = buf->p;
|
buf->p = buf->ptr = NULL;
|
||||||
return buf->p->payload;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @ingroup netbuf
|
||||||
* @ingroup netbuf
|
* Let a netbuf reference existing (non-volatile) data.
|
||||||
* Free the packet buffer included in a netbuf
|
*
|
||||||
*
|
* @param buf netbuf which should reference the data
|
||||||
* @param buf pointer to the netbuf which contains the packet buffer to free
|
* @param dataptr pointer to the data to reference
|
||||||
*/
|
* @param size size of the data
|
||||||
void
|
* @return ERR_OK if data is referenced
|
||||||
netbuf_free(struct netbuf *buf)
|
* ERR_MEM if data couldn't be referenced due to lack of memory
|
||||||
{
|
*/
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
err_t
|
||||||
if (buf->p != NULL) {
|
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
||||||
pbuf_free(buf->p);
|
{
|
||||||
}
|
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
|
||||||
buf->p = buf->ptr = NULL;
|
if (buf->p != NULL) {
|
||||||
}
|
pbuf_free(buf->p);
|
||||||
|
}
|
||||||
/**
|
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||||
* @ingroup netbuf
|
if (buf->p == NULL) {
|
||||||
* Let a netbuf reference existing (non-volatile) data.
|
buf->ptr = NULL;
|
||||||
*
|
return ERR_MEM;
|
||||||
* @param buf netbuf which should reference the data
|
}
|
||||||
* @param dataptr pointer to the data to reference
|
((struct pbuf_rom*)buf->p)->payload = dataptr;
|
||||||
* @param size size of the data
|
buf->p->len = buf->p->tot_len = size;
|
||||||
* @return ERR_OK if data is referenced
|
buf->ptr = buf->p;
|
||||||
* ERR_MEM if data couldn't be referenced due to lack of memory
|
return ERR_OK;
|
||||||
*/
|
}
|
||||||
err_t
|
|
||||||
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
/**
|
||||||
{
|
* @ingroup netbuf
|
||||||
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
|
* Chain one netbuf to another (@see pbuf_chain)
|
||||||
if (buf->p != NULL) {
|
*
|
||||||
pbuf_free(buf->p);
|
* @param head the first netbuf
|
||||||
}
|
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
|
||||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
*/
|
||||||
if (buf->p == NULL) {
|
void
|
||||||
buf->ptr = NULL;
|
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||||
return ERR_MEM;
|
{
|
||||||
}
|
LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
|
||||||
((struct pbuf_rom*)buf->p)->payload = dataptr;
|
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
||||||
buf->p->len = buf->p->tot_len = size;
|
pbuf_cat(head->p, tail->p);
|
||||||
buf->ptr = buf->p;
|
head->ptr = head->p;
|
||||||
return ERR_OK;
|
memp_free(MEMP_NETBUF, tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup netbuf
|
* @ingroup netbuf
|
||||||
* Chain one netbuf to another (@see pbuf_chain)
|
* Get the data pointer and length of the data inside a netbuf.
|
||||||
*
|
*
|
||||||
* @param head the first netbuf
|
* @param buf netbuf to get the data from
|
||||||
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
|
* @param dataptr pointer to a void pointer where to store the data pointer
|
||||||
*/
|
* @param len pointer to an u16_t where the length of the data is stored
|
||||||
void
|
* @return ERR_OK if the information was retrieved,
|
||||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
* ERR_BUF on error.
|
||||||
{
|
*/
|
||||||
LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
|
err_t
|
||||||
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
||||||
pbuf_cat(head->p, tail->p);
|
{
|
||||||
head->ptr = head->p;
|
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
|
||||||
memp_free(MEMP_NETBUF, tail);
|
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
|
||||||
}
|
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
|
||||||
|
|
||||||
/**
|
if (buf->ptr == NULL) {
|
||||||
* @ingroup netbuf
|
return ERR_BUF;
|
||||||
* Get the data pointer and length of the data inside a netbuf.
|
}
|
||||||
*
|
*dataptr = buf->ptr->payload;
|
||||||
* @param buf netbuf to get the data from
|
*len = buf->ptr->len;
|
||||||
* @param dataptr pointer to a void pointer where to store the data pointer
|
return ERR_OK;
|
||||||
* @param len pointer to an u16_t where the length of the data is stored
|
}
|
||||||
* @return ERR_OK if the information was retrieved,
|
|
||||||
* ERR_BUF on error.
|
/**
|
||||||
*/
|
* @ingroup netbuf
|
||||||
err_t
|
* Move the current data pointer of a packet buffer contained in a netbuf
|
||||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
* to the next part.
|
||||||
{
|
* The packet buffer itself is not modified.
|
||||||
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
|
*
|
||||||
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
|
* @param buf the netbuf to modify
|
||||||
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
|
* @return -1 if there is no next part
|
||||||
|
* 1 if moved to the next part but now there is no next part
|
||||||
if (buf->ptr == NULL) {
|
* 0 if moved to the next part and there are still more parts
|
||||||
return ERR_BUF;
|
*/
|
||||||
}
|
s8_t
|
||||||
*dataptr = buf->ptr->payload;
|
netbuf_next(struct netbuf *buf)
|
||||||
*len = buf->ptr->len;
|
{
|
||||||
return ERR_OK;
|
LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
|
||||||
}
|
if (buf->ptr->next == NULL) {
|
||||||
|
return -1;
|
||||||
/**
|
}
|
||||||
* @ingroup netbuf
|
buf->ptr = buf->ptr->next;
|
||||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
if (buf->ptr->next == NULL) {
|
||||||
* to the next part.
|
return 1;
|
||||||
* The packet buffer itself is not modified.
|
}
|
||||||
*
|
return 0;
|
||||||
* @param buf the netbuf to modify
|
}
|
||||||
* @return -1 if there is no next part
|
|
||||||
* 1 if moved to the next part but now there is no next part
|
/**
|
||||||
* 0 if moved to the next part and there are still more parts
|
* @ingroup netbuf
|
||||||
*/
|
* Move the current data pointer of a packet buffer contained in a netbuf
|
||||||
s8_t
|
* to the beginning of the packet.
|
||||||
netbuf_next(struct netbuf *buf)
|
* The packet buffer itself is not modified.
|
||||||
{
|
*
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;);
|
* @param buf the netbuf to modify
|
||||||
if (buf->ptr->next == NULL) {
|
*/
|
||||||
return -1;
|
void
|
||||||
}
|
netbuf_first(struct netbuf *buf)
|
||||||
buf->ptr = buf->ptr->next;
|
{
|
||||||
if (buf->ptr->next == NULL) {
|
LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
|
||||||
return 1;
|
buf->ptr = buf->p;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
#endif /* LWIP_NETCONN */
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup netbuf
|
|
||||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
|
||||||
* to the beginning of the packet.
|
|
||||||
* The packet buffer itself is not modified.
|
|
||||||
*
|
|
||||||
* @param buf the netbuf to modify
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
netbuf_first(struct netbuf *buf)
|
|
||||||
{
|
|
||||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
|
||||||
buf->ptr = buf->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_NETCONN */
|
|
||||||
|
|||||||
830
ext/lwip/src/api/netdb.c
Normal file → Executable file
830
ext/lwip/src/api/netdb.c
Normal file → Executable file
@@ -1,417 +1,413 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* API functions for name resolving
|
* API functions for name resolving
|
||||||
*
|
*
|
||||||
*/
|
* @defgroup netdbapi NETDB API
|
||||||
|
* @ingroup socket
|
||||||
/*
|
*/
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
/*
|
||||||
*
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* are permitted provided that the following conditions are met:
|
||||||
* this list of conditions and the following disclaimer.
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer.
|
||||||
* and/or other materials provided with the distribution.
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* derived from this software without specific prior written permission.
|
* and/or other materials provided with the distribution.
|
||||||
*
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* derived from this software without specific prior written permission.
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
*
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* OF SUCH DAMAGE.
|
* 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
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Author: Simon Goldschmidt
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
*/
|
* Author: Simon Goldschmidt
|
||||||
|
*
|
||||||
|
*/
|
||||||
/**
|
|
||||||
* @defgroup netdbapi NETDB API
|
#include "lwip/netdb.h"
|
||||||
* @ingroup socket
|
|
||||||
*/
|
#if LWIP_DNS && LWIP_SOCKET
|
||||||
|
|
||||||
#include "lwip/netdb.h"
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
#if LWIP_DNS && LWIP_SOCKET
|
#include "lwip/memp.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/api.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/dns.h"
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
#include <string.h> /* memset */
|
||||||
#include "lwip/api.h"
|
#include <stdlib.h> /* atoi */
|
||||||
#include "lwip/dns.h"
|
|
||||||
|
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||||
#include <string.h>
|
struct gethostbyname_r_helper {
|
||||||
#include <stdlib.h>
|
ip_addr_t *addr_list[2];
|
||||||
|
ip_addr_t addr;
|
||||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
char *aliases;
|
||||||
struct gethostbyname_r_helper {
|
};
|
||||||
ip_addr_t *addr_list[2];
|
|
||||||
ip_addr_t addr;
|
/** h_errno is exported in netdb.h for access by applications. */
|
||||||
char *aliases;
|
#if LWIP_DNS_API_DECLARE_H_ERRNO
|
||||||
};
|
int h_errno;
|
||||||
|
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
|
||||||
/** h_errno is exported in netdb.h for access by applications. */
|
|
||||||
#if LWIP_DNS_API_DECLARE_H_ERRNO
|
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
|
||||||
int h_errno;
|
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
|
||||||
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
|
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
|
||||||
|
#define LWIP_DNS_API_HOSTENT_STORAGE 0
|
||||||
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
|
#endif
|
||||||
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
|
|
||||||
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
|
/** define "hostent" variables storage */
|
||||||
#define LWIP_DNS_API_HOSTENT_STORAGE 0
|
#if LWIP_DNS_API_HOSTENT_STORAGE
|
||||||
#endif
|
#define HOSTENT_STORAGE
|
||||||
|
#else
|
||||||
/** define "hostent" variables storage */
|
#define HOSTENT_STORAGE static
|
||||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
|
||||||
#define HOSTENT_STORAGE
|
|
||||||
#else
|
/**
|
||||||
#define HOSTENT_STORAGE static
|
* Returns an entry containing addresses of address family AF_INET
|
||||||
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
|
* for the host with name name.
|
||||||
|
* Due to dns_gethostbyname limitations, only one address is returned.
|
||||||
/**
|
*
|
||||||
* Returns an entry containing addresses of address family AF_INET
|
* @param name the hostname to resolve
|
||||||
* for the host with name name.
|
* @return an entry containing addresses of address family AF_INET
|
||||||
* Due to dns_gethostbyname limitations, only one address is returned.
|
* for the host with name name
|
||||||
*
|
*/
|
||||||
* @param name the hostname to resolve
|
struct hostent*
|
||||||
* @return an entry containing addresses of address family AF_INET
|
lwip_gethostbyname(const char *name)
|
||||||
* for the host with name name
|
{
|
||||||
*/
|
err_t err;
|
||||||
struct hostent*
|
ip_addr_t addr;
|
||||||
lwip_gethostbyname(const char *name)
|
|
||||||
{
|
/* buffer variables for lwip_gethostbyname() */
|
||||||
err_t err;
|
HOSTENT_STORAGE struct hostent s_hostent;
|
||||||
ip_addr_t addr;
|
HOSTENT_STORAGE char *s_aliases;
|
||||||
|
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
|
||||||
/* buffer variables for lwip_gethostbyname() */
|
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
|
||||||
HOSTENT_STORAGE struct hostent s_hostent;
|
HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
|
||||||
HOSTENT_STORAGE char *s_aliases;
|
|
||||||
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
|
/* query host IP address */
|
||||||
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
|
err = netconn_gethostbyname(name, &addr);
|
||||||
HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
|
if (err != ERR_OK) {
|
||||||
|
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
||||||
/* query host IP address */
|
h_errno = HOST_NOT_FOUND;
|
||||||
err = netconn_gethostbyname(name, &addr);
|
return NULL;
|
||||||
if (err != ERR_OK) {
|
}
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
|
||||||
h_errno = HOST_NOT_FOUND;
|
/* fill hostent */
|
||||||
return NULL;
|
s_hostent_addr = addr;
|
||||||
}
|
s_phostent_addr[0] = &s_hostent_addr;
|
||||||
|
s_phostent_addr[1] = NULL;
|
||||||
/* fill hostent */
|
strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
|
||||||
s_hostent_addr = addr;
|
s_hostname[DNS_MAX_NAME_LENGTH] = 0;
|
||||||
s_phostent_addr[0] = &s_hostent_addr;
|
s_hostent.h_name = s_hostname;
|
||||||
s_phostent_addr[1] = NULL;
|
s_aliases = NULL;
|
||||||
strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
|
s_hostent.h_aliases = &s_aliases;
|
||||||
s_hostname[DNS_MAX_NAME_LENGTH] = 0;
|
s_hostent.h_addrtype = AF_INET;
|
||||||
s_hostent.h_name = s_hostname;
|
s_hostent.h_length = sizeof(ip_addr_t);
|
||||||
s_aliases = NULL;
|
s_hostent.h_addr_list = (char**)&s_phostent_addr;
|
||||||
s_hostent.h_aliases = &s_aliases;
|
|
||||||
s_hostent.h_addrtype = AF_INET;
|
#if DNS_DEBUG
|
||||||
s_hostent.h_length = sizeof(ip_addr_t);
|
/* dump hostent */
|
||||||
s_hostent.h_addr_list = (char**)&s_phostent_addr;
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
||||||
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases));
|
||||||
#if DNS_DEBUG
|
/* h_aliases are always empty */
|
||||||
/* dump hostent */
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases));
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list));
|
||||||
/* h_aliases are always empty */
|
if (s_hostent.h_addr_list != NULL) {
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
u8_t idx;
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
|
for (idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list));
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
||||||
if (s_hostent.h_addr_list != NULL) {
|
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
|
||||||
u8_t idx;
|
}
|
||||||
for (idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
}
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
#endif /* DNS_DEBUG */
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
|
|
||||||
}
|
#if LWIP_DNS_API_HOSTENT_STORAGE
|
||||||
}
|
/* this function should return the "per-thread" hostent after copy from s_hostent */
|
||||||
#endif /* DNS_DEBUG */
|
return sys_thread_hostent(&s_hostent);
|
||||||
|
#else
|
||||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
return &s_hostent;
|
||||||
/* this function should return the "per-thread" hostent after copy from s_hostent */
|
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
|
||||||
return sys_thread_hostent(&s_hostent);
|
}
|
||||||
#else
|
|
||||||
return &s_hostent;
|
/**
|
||||||
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
|
* Thread-safe variant of lwip_gethostbyname: instead of using a static
|
||||||
}
|
* buffer, this function takes buffer and errno pointers as arguments
|
||||||
|
* and uses these for the result.
|
||||||
/**
|
*
|
||||||
* Thread-safe variant of lwip_gethostbyname: instead of using a static
|
* @param name the hostname to resolve
|
||||||
* buffer, this function takes buffer and errno pointers as arguments
|
* @param ret pre-allocated struct where to store the result
|
||||||
* and uses these for the result.
|
* @param buf pre-allocated buffer where to store additional data
|
||||||
*
|
* @param buflen the size of buf
|
||||||
* @param name the hostname to resolve
|
* @param result pointer to a hostent pointer that is set to ret on success
|
||||||
* @param ret pre-allocated struct where to store the result
|
* and set to zero on error
|
||||||
* @param buf pre-allocated buffer where to store additional data
|
* @param h_errnop pointer to an int where to store errors (instead of modifying
|
||||||
* @param buflen the size of buf
|
* the global h_errno)
|
||||||
* @param result pointer to a hostent pointer that is set to ret on success
|
* @return 0 on success, non-zero on error, additional error information
|
||||||
* and set to zero on error
|
* is stored in *h_errnop instead of h_errno to be thread-safe
|
||||||
* @param h_errnop pointer to an int where to store errors (instead of modifying
|
*/
|
||||||
* the global h_errno)
|
int
|
||||||
* @return 0 on success, non-zero on error, additional error information
|
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||||
* is stored in *h_errnop instead of h_errno to be thread-safe
|
size_t buflen, struct hostent **result, int *h_errnop)
|
||||||
*/
|
{
|
||||||
int
|
err_t err;
|
||||||
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
struct gethostbyname_r_helper *h;
|
||||||
size_t buflen, struct hostent **result, int *h_errnop)
|
char *hostname;
|
||||||
{
|
size_t namelen;
|
||||||
err_t err;
|
int lh_errno;
|
||||||
struct gethostbyname_r_helper *h;
|
|
||||||
char *hostname;
|
if (h_errnop == NULL) {
|
||||||
size_t namelen;
|
/* ensure h_errnop is never NULL */
|
||||||
int lh_errno;
|
h_errnop = &lh_errno;
|
||||||
|
}
|
||||||
if (h_errnop == NULL) {
|
|
||||||
/* ensure h_errnop is never NULL */
|
if (result == NULL) {
|
||||||
h_errnop = &lh_errno;
|
/* not all arguments given */
|
||||||
}
|
*h_errnop = EINVAL;
|
||||||
|
return -1;
|
||||||
if (result == NULL) {
|
}
|
||||||
/* not all arguments given */
|
/* first thing to do: set *result to nothing */
|
||||||
*h_errnop = EINVAL;
|
*result = NULL;
|
||||||
return -1;
|
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
|
||||||
}
|
/* not all arguments given */
|
||||||
/* first thing to do: set *result to nothing */
|
*h_errnop = EINVAL;
|
||||||
*result = NULL;
|
return -1;
|
||||||
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
|
}
|
||||||
/* not all arguments given */
|
|
||||||
*h_errnop = EINVAL;
|
namelen = strlen(name);
|
||||||
return -1;
|
if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
|
||||||
}
|
/* buf can't hold the data needed + a copy of name */
|
||||||
|
*h_errnop = ERANGE;
|
||||||
namelen = strlen(name);
|
return -1;
|
||||||
if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
|
}
|
||||||
/* buf can't hold the data needed + a copy of name */
|
|
||||||
*h_errnop = ERANGE;
|
h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
|
||||||
return -1;
|
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
|
||||||
}
|
|
||||||
|
/* query host IP address */
|
||||||
h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
|
err = netconn_gethostbyname(name, &h->addr);
|
||||||
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
|
if (err != ERR_OK) {
|
||||||
|
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
||||||
/* query host IP address */
|
*h_errnop = HOST_NOT_FOUND;
|
||||||
err = netconn_gethostbyname(name, &h->addr);
|
return -1;
|
||||||
if (err != ERR_OK) {
|
}
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
|
||||||
*h_errnop = HOST_NOT_FOUND;
|
/* copy the hostname into buf */
|
||||||
return -1;
|
MEMCPY(hostname, name, namelen);
|
||||||
}
|
hostname[namelen] = 0;
|
||||||
|
|
||||||
/* copy the hostname into buf */
|
/* fill hostent */
|
||||||
MEMCPY(hostname, name, namelen);
|
h->addr_list[0] = &h->addr;
|
||||||
hostname[namelen] = 0;
|
h->addr_list[1] = NULL;
|
||||||
|
h->aliases = NULL;
|
||||||
/* fill hostent */
|
ret->h_name = hostname;
|
||||||
h->addr_list[0] = &h->addr;
|
ret->h_aliases = &h->aliases;
|
||||||
h->addr_list[1] = NULL;
|
ret->h_addrtype = AF_INET;
|
||||||
h->aliases = NULL;
|
ret->h_length = sizeof(ip_addr_t);
|
||||||
ret->h_name = hostname;
|
ret->h_addr_list = (char**)&h->addr_list;
|
||||||
ret->h_aliases = &h->aliases;
|
|
||||||
ret->h_addrtype = AF_INET;
|
/* set result != NULL */
|
||||||
ret->h_length = sizeof(ip_addr_t);
|
*result = ret;
|
||||||
ret->h_addr_list = (char**)&h->addr_list;
|
|
||||||
|
/* return success */
|
||||||
/* set result != NULL */
|
return 0;
|
||||||
*result = ret;
|
}
|
||||||
|
|
||||||
/* return success */
|
/**
|
||||||
return 0;
|
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
|
||||||
}
|
* any additional storage associated with those structures. If the ai_next field
|
||||||
|
* of the structure is not null, the entire list of structures is freed.
|
||||||
/**
|
*
|
||||||
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
|
* @param ai struct addrinfo to free
|
||||||
* any additional storage associated with those structures. If the ai_next field
|
*/
|
||||||
* of the structure is not null, the entire list of structures is freed.
|
void
|
||||||
*
|
lwip_freeaddrinfo(struct addrinfo *ai)
|
||||||
* @param ai struct addrinfo to free
|
{
|
||||||
*/
|
struct addrinfo *next;
|
||||||
void
|
|
||||||
lwip_freeaddrinfo(struct addrinfo *ai)
|
while (ai != NULL) {
|
||||||
{
|
next = ai->ai_next;
|
||||||
struct addrinfo *next;
|
memp_free(MEMP_NETDB, ai);
|
||||||
|
ai = next;
|
||||||
while (ai != NULL) {
|
}
|
||||||
next = ai->ai_next;
|
}
|
||||||
memp_free(MEMP_NETDB, ai);
|
|
||||||
ai = next;
|
/**
|
||||||
}
|
* Translates the name of a service location (for example, a host name) and/or
|
||||||
}
|
* a service name and returns a set of socket addresses and associated
|
||||||
|
* information to be used in creating a socket with which to address the
|
||||||
/**
|
* specified service.
|
||||||
* Translates the name of a service location (for example, a host name) and/or
|
* Memory for the result is allocated internally and must be freed by calling
|
||||||
* a service name and returns a set of socket addresses and associated
|
* lwip_freeaddrinfo()!
|
||||||
* information to be used in creating a socket with which to address the
|
*
|
||||||
* specified service.
|
* Due to a limitation in dns_gethostbyname, only the first address of a
|
||||||
* Memory for the result is allocated internally and must be freed by calling
|
* host is returned.
|
||||||
* lwip_freeaddrinfo()!
|
* Also, service names are not supported (only port numbers)!
|
||||||
*
|
*
|
||||||
* Due to a limitation in dns_gethostbyname, only the first address of a
|
* @param nodename descriptive name or address string of the host
|
||||||
* host is returned.
|
* (may be NULL -> local address)
|
||||||
* Also, service names are not supported (only port numbers)!
|
* @param servname port number as string of NULL
|
||||||
*
|
* @param hints structure containing input values that set socktype and protocol
|
||||||
* @param nodename descriptive name or address string of the host
|
* @param res pointer to a pointer where to store the result (set to NULL on failure)
|
||||||
* (may be NULL -> local address)
|
* @return 0 on success, non-zero on failure
|
||||||
* @param servname port number as string of NULL
|
*
|
||||||
* @param hints structure containing input values that set socktype and protocol
|
* @todo: implement AI_V4MAPPED, AI_ADDRCONFIG
|
||||||
* @param res pointer to a pointer where to store the result (set to NULL on failure)
|
*/
|
||||||
* @return 0 on success, non-zero on failure
|
int
|
||||||
*
|
lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||||
* @todo: implement AI_V4MAPPED, AI_ADDRCONFIG
|
const struct addrinfo *hints, struct addrinfo **res)
|
||||||
*/
|
{
|
||||||
int
|
err_t err;
|
||||||
lwip_getaddrinfo(const char *nodename, const char *servname,
|
ip_addr_t addr;
|
||||||
const struct addrinfo *hints, struct addrinfo **res)
|
struct addrinfo *ai;
|
||||||
{
|
struct sockaddr_storage *sa = NULL;
|
||||||
err_t err;
|
int port_nr = 0;
|
||||||
ip_addr_t addr;
|
size_t total_size;
|
||||||
struct addrinfo *ai;
|
size_t namelen = 0;
|
||||||
struct sockaddr_storage *sa = NULL;
|
int ai_family;
|
||||||
int port_nr = 0;
|
|
||||||
size_t total_size;
|
if (res == NULL) {
|
||||||
size_t namelen = 0;
|
return EAI_FAIL;
|
||||||
int ai_family;
|
}
|
||||||
|
*res = NULL;
|
||||||
if (res == NULL) {
|
if ((nodename == NULL) && (servname == NULL)) {
|
||||||
return EAI_FAIL;
|
return EAI_NONAME;
|
||||||
}
|
}
|
||||||
*res = NULL;
|
|
||||||
if ((nodename == NULL) && (servname == NULL)) {
|
if (hints != NULL) {
|
||||||
return EAI_NONAME;
|
ai_family = hints->ai_family;
|
||||||
}
|
if ((ai_family != AF_UNSPEC)
|
||||||
|
#if LWIP_IPV4
|
||||||
if (hints != NULL) {
|
&& (ai_family != AF_INET)
|
||||||
ai_family = hints->ai_family;
|
#endif /* LWIP_IPV4 */
|
||||||
if ((ai_family != AF_UNSPEC)
|
#if LWIP_IPV6
|
||||||
#if LWIP_IPV4
|
&& (ai_family != AF_INET6)
|
||||||
&& (ai_family != AF_INET)
|
#endif /* LWIP_IPV6 */
|
||||||
#endif /* LWIP_IPV4 */
|
) {
|
||||||
#if LWIP_IPV6
|
return EAI_FAMILY;
|
||||||
&& (ai_family != AF_INET6)
|
}
|
||||||
#endif /* LWIP_IPV6 */
|
} else {
|
||||||
) {
|
ai_family = AF_UNSPEC;
|
||||||
return EAI_FAMILY;
|
}
|
||||||
}
|
|
||||||
} else {
|
if (servname != NULL) {
|
||||||
ai_family = AF_UNSPEC;
|
/* service name specified: convert to port number
|
||||||
}
|
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
|
||||||
|
port_nr = atoi(servname);
|
||||||
if (servname != NULL) {
|
if ((port_nr <= 0) || (port_nr > 0xffff)) {
|
||||||
/* service name specified: convert to port number
|
return EAI_SERVICE;
|
||||||
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
|
}
|
||||||
port_nr = atoi(servname);
|
}
|
||||||
if ((port_nr <= 0) || (port_nr > 0xffff)) {
|
|
||||||
return EAI_SERVICE;
|
if (nodename != NULL) {
|
||||||
}
|
/* service location specified, try to resolve */
|
||||||
}
|
if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
|
||||||
|
/* no DNS lookup, just parse for an address string */
|
||||||
if (nodename != NULL) {
|
if (!ipaddr_aton(nodename, &addr)) {
|
||||||
/* service location specified, try to resolve */
|
return EAI_NONAME;
|
||||||
if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
|
}
|
||||||
/* no DNS lookup, just parse for an address string */
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
if (!ipaddr_aton(nodename, &addr)) {
|
if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
|
||||||
return EAI_NONAME;
|
(IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) {
|
||||||
}
|
return EAI_NONAME;
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
}
|
||||||
if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
(IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) {
|
} else {
|
||||||
return EAI_NONAME;
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
}
|
/* AF_UNSPEC: prefer IPv4 */
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
u8_t type = NETCONN_DNS_IPV4_IPV6;
|
||||||
} else {
|
if (ai_family == AF_INET) {
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
type = NETCONN_DNS_IPV4;
|
||||||
/* AF_UNSPEC: prefer IPv4 */
|
} else if (ai_family == AF_INET6) {
|
||||||
u8_t type = NETCONN_DNS_IPV4_IPV6;
|
type = NETCONN_DNS_IPV6;
|
||||||
if (ai_family == AF_INET) {
|
}
|
||||||
type = NETCONN_DNS_IPV4;
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
} else if (ai_family == AF_INET6) {
|
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
|
||||||
type = NETCONN_DNS_IPV6;
|
if (err != ERR_OK) {
|
||||||
}
|
return EAI_FAIL;
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
}
|
||||||
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
|
}
|
||||||
if (err != ERR_OK) {
|
} else {
|
||||||
return EAI_FAIL;
|
/* service location specified, use loopback address */
|
||||||
}
|
if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
|
||||||
}
|
ip_addr_set_any(ai_family == AF_INET6, &addr);
|
||||||
} else {
|
} else {
|
||||||
/* service location specified, use loopback address */
|
ip_addr_set_loopback(ai_family == AF_INET6, &addr);
|
||||||
if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
|
}
|
||||||
ip_addr_set_any(ai_family == AF_INET6, &addr);
|
}
|
||||||
} else {
|
|
||||||
ip_addr_set_loopback(ai_family == AF_INET6, &addr);
|
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
|
||||||
}
|
if (nodename != NULL) {
|
||||||
}
|
namelen = strlen(nodename);
|
||||||
|
if (namelen > DNS_MAX_NAME_LENGTH) {
|
||||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
|
/* invalid name length */
|
||||||
if (nodename != NULL) {
|
return EAI_FAIL;
|
||||||
namelen = strlen(nodename);
|
}
|
||||||
if (namelen > DNS_MAX_NAME_LENGTH) {
|
LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
|
||||||
/* invalid name length */
|
total_size += namelen + 1;
|
||||||
return EAI_FAIL;
|
}
|
||||||
}
|
/* If this fails, please report to lwip-devel! :-) */
|
||||||
LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
|
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
|
||||||
total_size += namelen + 1;
|
total_size <= NETDB_ELEM_SIZE);
|
||||||
}
|
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
|
||||||
/* If this fails, please report to lwip-devel! :-) */
|
if (ai == NULL) {
|
||||||
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
|
return EAI_MEMORY;
|
||||||
total_size <= NETDB_ELEM_SIZE);
|
}
|
||||||
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
|
memset(ai, 0, total_size);
|
||||||
if (ai == NULL) {
|
/* cast through void* to get rid of alignment warnings */
|
||||||
return EAI_MEMORY;
|
sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo));
|
||||||
}
|
if (IP_IS_V6_VAL(addr)) {
|
||||||
memset(ai, 0, total_size);
|
#if LWIP_IPV6
|
||||||
/* cast through void* to get rid of alignment warnings */
|
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
|
||||||
sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo));
|
/* set up sockaddr */
|
||||||
if (IP_IS_V6_VAL(addr)) {
|
inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
|
||||||
#if LWIP_IPV6
|
sa6->sin6_family = AF_INET6;
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
|
sa6->sin6_len = sizeof(struct sockaddr_in6);
|
||||||
/* set up sockaddr */
|
sa6->sin6_port = lwip_htons((u16_t)port_nr);
|
||||||
inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
|
ai->ai_family = AF_INET6;
|
||||||
sa6->sin6_family = AF_INET6;
|
#endif /* LWIP_IPV6 */
|
||||||
sa6->sin6_len = sizeof(struct sockaddr_in6);
|
} else {
|
||||||
sa6->sin6_port = htons((u16_t)port_nr);
|
#if LWIP_IPV4
|
||||||
ai->ai_family = AF_INET6;
|
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
|
||||||
#endif /* LWIP_IPV6 */
|
/* set up sockaddr */
|
||||||
} else {
|
inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr));
|
||||||
#if LWIP_IPV4
|
sa4->sin_family = AF_INET;
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
|
sa4->sin_len = sizeof(struct sockaddr_in);
|
||||||
/* set up sockaddr */
|
sa4->sin_port = lwip_htons((u16_t)port_nr);
|
||||||
inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
|
ai->ai_family = AF_INET;
|
||||||
sa4->sin_family = AF_INET;
|
#endif /* LWIP_IPV4 */
|
||||||
sa4->sin_len = sizeof(struct sockaddr_in);
|
}
|
||||||
sa4->sin_port = htons((u16_t)port_nr);
|
|
||||||
ai->ai_family = AF_INET;
|
/* set up addrinfo */
|
||||||
#endif /* LWIP_IPV4 */
|
if (hints != NULL) {
|
||||||
}
|
/* copy socktype & protocol from hints if specified */
|
||||||
|
ai->ai_socktype = hints->ai_socktype;
|
||||||
/* set up addrinfo */
|
ai->ai_protocol = hints->ai_protocol;
|
||||||
if (hints != NULL) {
|
}
|
||||||
/* copy socktype & protocol from hints if specified */
|
if (nodename != NULL) {
|
||||||
ai->ai_socktype = hints->ai_socktype;
|
/* copy nodename to canonname if specified */
|
||||||
ai->ai_protocol = hints->ai_protocol;
|
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
|
||||||
}
|
MEMCPY(ai->ai_canonname, nodename, namelen);
|
||||||
if (nodename != NULL) {
|
ai->ai_canonname[namelen] = 0;
|
||||||
/* copy nodename to canonname if specified */
|
}
|
||||||
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
|
ai->ai_addrlen = sizeof(struct sockaddr_storage);
|
||||||
MEMCPY(ai->ai_canonname, nodename, namelen);
|
ai->ai_addr = (struct sockaddr*)sa;
|
||||||
ai->ai_canonname[namelen] = 0;
|
|
||||||
}
|
*res = ai;
|
||||||
ai->ai_addrlen = sizeof(struct sockaddr_storage);
|
|
||||||
ai->ai_addr = (struct sockaddr*)sa;
|
return 0;
|
||||||
|
}
|
||||||
*res = ai;
|
|
||||||
|
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
|
||||||
|
|||||||
445
ext/lwip/src/api/netifapi.c
Normal file → Executable file
445
ext/lwip/src/api/netifapi.c
Normal file → Executable file
@@ -1,224 +1,221 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Network Interface Sequential API module
|
* Network Interface Sequential API module
|
||||||
*
|
*
|
||||||
*/
|
* @defgroup netifapi NETIF API
|
||||||
|
* @ingroup sequential_api
|
||||||
/*
|
* Thread-safe functions to be called from non-TCPIP threads
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
*
|
||||||
* are permitted provided that the following conditions are met:
|
* @defgroup netifapi_netif NETIF related
|
||||||
*
|
* @ingroup netifapi
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* To be called from non-TCPIP threads
|
||||||
* 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.
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* are permitted provided that the following conditions are met:
|
||||||
* derived from this software without specific prior written permission.
|
*
|
||||||
*
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* this list of conditions and the following disclaimer.
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* and/or other materials provided with the distribution.
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* derived from this software without specific prior written permission.
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
*
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* OF SUCH DAMAGE.
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
*
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 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
|
||||||
* @defgroup netifapi NETIF API
|
* OF SUCH DAMAGE.
|
||||||
* @ingroup threadsafe_api
|
*
|
||||||
* Thread-safe functions to be called from non-TCPIP threads
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* @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 */
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
#include "lwip/netifapi.h"
|
||||||
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
|
#include "lwip/memp.h"
|
||||||
|
#include "lwip/priv/tcpip_priv.h"
|
||||||
#include "lwip/netifapi.h"
|
|
||||||
#include "lwip/memp.h"
|
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name)
|
||||||
|
#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
|
||||||
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
|
#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
|
||||||
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name)
|
|
||||||
#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
|
/**
|
||||||
#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
|
* Call netif_add() inside the tcpip_thread context.
|
||||||
|
*/
|
||||||
/**
|
static err_t
|
||||||
* Call netif_add() inside the tcpip_thread context.
|
netifapi_do_netif_add(struct tcpip_api_call_data *m)
|
||||||
*/
|
{
|
||||||
static err_t
|
/* cast through void* to silence alignment warnings.
|
||||||
netifapi_do_netif_add(struct tcpip_api_call_data *m)
|
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
||||||
{
|
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
||||||
/* cast through void* to silence alignment warnings.
|
|
||||||
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
if (!netif_add( msg->netif,
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
#if LWIP_IPV4
|
||||||
|
API_EXPR_REF(msg->msg.add.ipaddr),
|
||||||
if (!netif_add( msg->netif,
|
API_EXPR_REF(msg->msg.add.netmask),
|
||||||
#if LWIP_IPV4
|
API_EXPR_REF(msg->msg.add.gw),
|
||||||
API_EXPR_REF(msg->msg.add.ipaddr),
|
#endif /* LWIP_IPV4 */
|
||||||
API_EXPR_REF(msg->msg.add.netmask),
|
msg->msg.add.state,
|
||||||
API_EXPR_REF(msg->msg.add.gw),
|
msg->msg.add.init,
|
||||||
#endif /* LWIP_IPV4 */
|
msg->msg.add.input)) {
|
||||||
msg->msg.add.state,
|
return ERR_IF;
|
||||||
msg->msg.add.init,
|
} else {
|
||||||
msg->msg.add.input)) {
|
return ERR_OK;
|
||||||
return ERR_IF;
|
}
|
||||||
} else {
|
}
|
||||||
return ERR_OK;
|
|
||||||
}
|
#if LWIP_IPV4
|
||||||
}
|
/**
|
||||||
|
* Call netif_set_addr() inside the tcpip_thread context.
|
||||||
#if LWIP_IPV4
|
*/
|
||||||
/**
|
static err_t
|
||||||
* Call netif_set_addr() inside the tcpip_thread context.
|
netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
|
||||||
*/
|
{
|
||||||
static err_t
|
/* cast through void* to silence alignment warnings.
|
||||||
netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
|
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
||||||
{
|
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
||||||
/* cast through void* to silence alignment warnings.
|
|
||||||
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
netif_set_addr( msg->netif,
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
API_EXPR_REF(msg->msg.add.ipaddr),
|
||||||
|
API_EXPR_REF(msg->msg.add.netmask),
|
||||||
netif_set_addr( msg->netif,
|
API_EXPR_REF(msg->msg.add.gw));
|
||||||
API_EXPR_REF(msg->msg.add.ipaddr),
|
return ERR_OK;
|
||||||
API_EXPR_REF(msg->msg.add.netmask),
|
}
|
||||||
API_EXPR_REF(msg->msg.add.gw));
|
#endif /* LWIP_IPV4 */
|
||||||
return ERR_OK;
|
|
||||||
}
|
/**
|
||||||
#endif /* LWIP_IPV4 */
|
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
|
||||||
|
* tcpip_thread context.
|
||||||
/**
|
*/
|
||||||
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
|
static err_t
|
||||||
* tcpip_thread context.
|
netifapi_do_netif_common(struct tcpip_api_call_data *m)
|
||||||
*/
|
{
|
||||||
static err_t
|
/* cast through void* to silence alignment warnings.
|
||||||
netifapi_do_netif_common(struct tcpip_api_call_data *m)
|
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
||||||
{
|
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
||||||
/* cast through void* to silence alignment warnings.
|
|
||||||
* We know it works because the structs have been instantiated as struct netifapi_msg */
|
if (msg->msg.common.errtfunc != NULL) {
|
||||||
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
|
return msg->msg.common.errtfunc(msg->netif);
|
||||||
|
} else {
|
||||||
if (msg->msg.common.errtfunc != NULL) {
|
msg->msg.common.voidfunc(msg->netif);
|
||||||
return msg->msg.common.errtfunc(msg->netif);
|
return ERR_OK;
|
||||||
} else {
|
}
|
||||||
msg->msg.common.voidfunc(msg->netif);
|
}
|
||||||
return ERR_OK;
|
|
||||||
}
|
/**
|
||||||
}
|
* @ingroup netifapi_netif
|
||||||
|
* Call netif_add() in a thread-safe way by running that function inside the
|
||||||
/**
|
* tcpip_thread context.
|
||||||
* @ingroup netifapi_netif
|
*
|
||||||
* Call netif_add() in a thread-safe way by running that function inside the
|
* @note for params @see netif_add()
|
||||||
* tcpip_thread context.
|
*/
|
||||||
*
|
err_t
|
||||||
* @note for params @see netif_add()
|
netifapi_netif_add(struct netif *netif,
|
||||||
*/
|
#if LWIP_IPV4
|
||||||
err_t
|
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
|
||||||
netifapi_netif_add(struct netif *netif,
|
#endif /* LWIP_IPV4 */
|
||||||
#if LWIP_IPV4
|
void *state, netif_init_fn init, netif_input_fn input)
|
||||||
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
|
{
|
||||||
#endif /* LWIP_IPV4 */
|
err_t err;
|
||||||
void *state, netif_init_fn init, netif_input_fn input)
|
NETIFAPI_VAR_DECLARE(msg);
|
||||||
{
|
NETIFAPI_VAR_ALLOC(msg);
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
#if LWIP_IPV4
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
if (ipaddr == NULL) {
|
||||||
|
ipaddr = IP4_ADDR_ANY4;
|
||||||
#if LWIP_IPV4
|
}
|
||||||
if (ipaddr == NULL) {
|
if (netmask == NULL) {
|
||||||
ipaddr = IP4_ADDR_ANY;
|
netmask = IP4_ADDR_ANY4;
|
||||||
}
|
}
|
||||||
if (netmask == NULL) {
|
if (gw == NULL) {
|
||||||
netmask = IP4_ADDR_ANY;
|
gw = IP4_ADDR_ANY4;
|
||||||
}
|
}
|
||||||
if (gw == NULL) {
|
#endif /* LWIP_IPV4 */
|
||||||
gw = IP4_ADDR_ANY;
|
|
||||||
}
|
NETIFAPI_VAR_REF(msg).netif = netif;
|
||||||
#endif /* LWIP_IPV4 */
|
#if LWIP_IPV4
|
||||||
|
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
||||||
#if LWIP_IPV4
|
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
#endif /* LWIP_IPV4 */
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
NETIFAPI_VAR_REF(msg).msg.add.state = state;
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
NETIFAPI_VAR_REF(msg).msg.add.init = init;
|
||||||
#endif /* LWIP_IPV4 */
|
NETIFAPI_VAR_REF(msg).msg.add.input = input;
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.state = state;
|
err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.init = init;
|
NETIFAPI_VAR_FREE(msg);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.input = input;
|
return err;
|
||||||
err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
|
}
|
||||||
NETIFAPI_VAR_FREE(msg);
|
|
||||||
return err;
|
#if LWIP_IPV4
|
||||||
}
|
/**
|
||||||
|
* @ingroup netifapi_netif
|
||||||
#if LWIP_IPV4
|
* Call netif_set_addr() in a thread-safe way by running that function inside the
|
||||||
/**
|
* tcpip_thread context.
|
||||||
* @ingroup netifapi_netif
|
*
|
||||||
* Call netif_set_addr() in a thread-safe way by running that function inside the
|
* @note for params @see netif_set_addr()
|
||||||
* tcpip_thread context.
|
*/
|
||||||
*
|
err_t
|
||||||
* @note for params @see netif_set_addr()
|
netifapi_netif_set_addr(struct netif *netif,
|
||||||
*/
|
const ip4_addr_t *ipaddr,
|
||||||
err_t
|
const ip4_addr_t *netmask,
|
||||||
netifapi_netif_set_addr(struct netif *netif,
|
const ip4_addr_t *gw)
|
||||||
const ip4_addr_t *ipaddr,
|
{
|
||||||
const ip4_addr_t *netmask,
|
err_t err;
|
||||||
const ip4_addr_t *gw)
|
NETIFAPI_VAR_DECLARE(msg);
|
||||||
{
|
NETIFAPI_VAR_ALLOC(msg);
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
if (ipaddr == NULL) {
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
ipaddr = IP4_ADDR_ANY4;
|
||||||
|
}
|
||||||
if (ipaddr == NULL) {
|
if (netmask == NULL) {
|
||||||
ipaddr = IP4_ADDR_ANY;
|
netmask = IP4_ADDR_ANY4;
|
||||||
}
|
}
|
||||||
if (netmask == NULL) {
|
if (gw == NULL) {
|
||||||
netmask = IP4_ADDR_ANY;
|
gw = IP4_ADDR_ANY4;
|
||||||
}
|
}
|
||||||
if (gw == NULL) {
|
|
||||||
gw = IP4_ADDR_ANY;
|
NETIFAPI_VAR_REF(msg).netif = netif;
|
||||||
}
|
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
||||||
|
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
|
err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
|
NETIFAPI_VAR_FREE(msg);
|
||||||
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
|
return err;
|
||||||
err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
|
}
|
||||||
NETIFAPI_VAR_FREE(msg);
|
#endif /* LWIP_IPV4 */
|
||||||
return err;
|
|
||||||
}
|
/**
|
||||||
#endif /* LWIP_IPV4 */
|
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
|
||||||
|
* way by running that function inside the tcpip_thread context.
|
||||||
/**
|
*
|
||||||
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
|
* @note use only for functions where there is only "netif" parameter.
|
||||||
* way by running that function inside the tcpip_thread context.
|
*/
|
||||||
*
|
err_t
|
||||||
* @note use only for functions where there is only "netif" parameter.
|
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
||||||
*/
|
netifapi_errt_fn errtfunc)
|
||||||
err_t
|
{
|
||||||
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
err_t err;
|
||||||
netifapi_errt_fn errtfunc)
|
NETIFAPI_VAR_DECLARE(msg);
|
||||||
{
|
NETIFAPI_VAR_ALLOC(msg);
|
||||||
err_t err;
|
|
||||||
NETIFAPI_VAR_DECLARE(msg);
|
NETIFAPI_VAR_REF(msg).netif = netif;
|
||||||
NETIFAPI_VAR_ALLOC(msg);
|
NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
|
||||||
|
NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
|
||||||
NETIFAPI_VAR_REF(msg).netif = netif;
|
err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
|
||||||
NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
|
NETIFAPI_VAR_FREE(msg);
|
||||||
NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
|
return err;
|
||||||
err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
|
}
|
||||||
NETIFAPI_VAR_FREE(msg);
|
|
||||||
return err;
|
#endif /* LWIP_NETIF_API */
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LWIP_NETIF_API */
|
|
||||||
|
|||||||
5630
ext/lwip/src/api/sockets.c
Normal file → Executable file
5630
ext/lwip/src/api/sockets.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1029
ext/lwip/src/api/tcpip.c
Normal file → Executable file
1029
ext/lwip/src/api/tcpip.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
179
ext/lwip/src/apps/httpd/fs.c
Executable file
179
ext/lwip/src/apps/httpd/fs.c
Executable file
@@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/httpd_opts.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "lwip/apps/fs.h"
|
||||||
|
#include "fsdata.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if HTTPD_USE_CUSTOM_FSDATA
|
||||||
|
#include "fsdata_custom.c"
|
||||||
|
#else /* HTTPD_USE_CUSTOM_FSDATA */
|
||||||
|
#include "fsdata.c"
|
||||||
|
#endif /* HTTPD_USE_CUSTOM_FSDATA */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if LWIP_HTTPD_CUSTOM_FILES
|
||||||
|
int fs_open_custom(struct fs_file *file, const char *name);
|
||||||
|
void fs_close_custom(struct fs_file *file);
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
u8_t fs_canread_custom(struct fs_file *file);
|
||||||
|
u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
|
||||||
|
int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
|
||||||
|
#else /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
int fs_read_custom(struct fs_file *file, char *buffer, int count);
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
#endif /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
err_t
|
||||||
|
fs_open(struct fs_file *file, const char *name)
|
||||||
|
{
|
||||||
|
const struct fsdata_file *f;
|
||||||
|
|
||||||
|
if ((file == NULL) || (name == NULL)) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_HTTPD_CUSTOM_FILES
|
||||||
|
if (fs_open_custom(file, name)) {
|
||||||
|
file->is_custom_file = 1;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
file->is_custom_file = 0;
|
||||||
|
#endif /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
|
||||||
|
for (f = FS_ROOT; f != NULL; f = f->next) {
|
||||||
|
if (!strcmp(name, (const char *)f->name)) {
|
||||||
|
file->data = (const char *)f->data;
|
||||||
|
file->len = f->len;
|
||||||
|
file->index = f->len;
|
||||||
|
file->pextension = NULL;
|
||||||
|
file->flags = f->flags;
|
||||||
|
#if HTTPD_PRECALCULATED_CHECKSUM
|
||||||
|
file->chksum_count = f->chksum_count;
|
||||||
|
file->chksum = f->chksum;
|
||||||
|
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
|
||||||
|
#if LWIP_HTTPD_FILE_STATE
|
||||||
|
file->state = fs_state_init(file, name);
|
||||||
|
#endif /* #if LWIP_HTTPD_FILE_STATE */
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* file not found */
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
fs_close(struct fs_file *file)
|
||||||
|
{
|
||||||
|
#if LWIP_HTTPD_CUSTOM_FILES
|
||||||
|
if (file->is_custom_file) {
|
||||||
|
fs_close_custom(file);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
#if LWIP_HTTPD_FILE_STATE
|
||||||
|
fs_state_free(file, file->state);
|
||||||
|
#endif /* #if LWIP_HTTPD_FILE_STATE */
|
||||||
|
LWIP_UNUSED_ARG(file);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
#if LWIP_HTTPD_DYNAMIC_FILE_READ
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
int
|
||||||
|
fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
|
||||||
|
#else /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
int
|
||||||
|
fs_read(struct fs_file *file, char *buffer, int count)
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
{
|
||||||
|
int read;
|
||||||
|
if(file->index == file->len) {
|
||||||
|
return FS_READ_EOF;
|
||||||
|
}
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
LWIP_UNUSED_ARG(callback_fn);
|
||||||
|
LWIP_UNUSED_ARG(callback_arg);
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
#if LWIP_HTTPD_CUSTOM_FILES
|
||||||
|
if (file->is_custom_file) {
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg);
|
||||||
|
#else /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
return fs_read_custom(file, buffer, count);
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
}
|
||||||
|
#endif /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
|
||||||
|
read = file->len - file->index;
|
||||||
|
if(read > count) {
|
||||||
|
read = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMCPY(buffer, (file->data + file->index), read);
|
||||||
|
file->index += read;
|
||||||
|
|
||||||
|
return(read);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
int
|
||||||
|
fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
|
||||||
|
{
|
||||||
|
if (file != NULL) {
|
||||||
|
#if LWIP_HTTPD_FS_ASYNC_READ
|
||||||
|
#if LWIP_HTTPD_CUSTOM_FILES
|
||||||
|
if (!fs_canread_custom(file)) {
|
||||||
|
if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
LWIP_UNUSED_ARG(callback_fn);
|
||||||
|
LWIP_UNUSED_ARG(callback_arg);
|
||||||
|
#endif /* LWIP_HTTPD_CUSTOM_FILES */
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
fs_bytes_left(struct fs_file *file)
|
||||||
|
{
|
||||||
|
return file->len - file->index;
|
||||||
|
}
|
||||||
21
ext/lwip/src/apps/httpd/fs/404.html
Executable file
21
ext/lwip/src/apps/httpd/fs/404.html
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
|
||||||
|
<body bgcolor="white" text="black">
|
||||||
|
|
||||||
|
<table width="100%">
|
||||||
|
<tr valign="top"><td width="80">
|
||||||
|
<a href="http://www.sics.se/"><img src="/img/sics.gif"
|
||||||
|
border="0" alt="SICS logo" title="SICS logo"></a>
|
||||||
|
</td><td width="500">
|
||||||
|
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
|
||||||
|
<h2>404 - Page not found</h2>
|
||||||
|
<p>
|
||||||
|
Sorry, the page you are requesting was not found on this
|
||||||
|
server.
|
||||||
|
</p>
|
||||||
|
</td><td>
|
||||||
|
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
ext/lwip/src/apps/httpd/fs/img/sics.gif
Executable file
BIN
ext/lwip/src/apps/httpd/fs/img/sics.gif
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 724 B |
47
ext/lwip/src/apps/httpd/fs/index.html
Executable file
47
ext/lwip/src/apps/httpd/fs/index.html
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
|
||||||
|
<body bgcolor="white" text="black">
|
||||||
|
|
||||||
|
<table width="100%">
|
||||||
|
<tr valign="top"><td width="80">
|
||||||
|
<a href="http://www.sics.se/"><img src="/img/sics.gif"
|
||||||
|
border="0" alt="SICS logo" title="SICS logo"></a>
|
||||||
|
</td><td width="500">
|
||||||
|
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
|
||||||
|
<p>
|
||||||
|
The web page you are watching was served by a simple web
|
||||||
|
server running on top of the lightweight TCP/IP stack <a
|
||||||
|
href="http://www.sics.se/~adam/lwip/">lwIP</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
lwIP is an open source implementation of the TCP/IP
|
||||||
|
protocol suite that was originally written by <a
|
||||||
|
href="http://www.sics.se/~adam/lwip/">Adam Dunkels
|
||||||
|
of the Swedish Institute of Computer Science</a> but now is
|
||||||
|
being actively developed by a team of developers
|
||||||
|
distributed world-wide. Since it's release, lwIP has
|
||||||
|
spurred a lot of interest and has been ported to several
|
||||||
|
platforms and operating systems. lwIP can be used either
|
||||||
|
with or without an underlying OS.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The focus of the lwIP TCP/IP implementation is to reduce
|
||||||
|
the RAM usage while still having a full scale TCP. This
|
||||||
|
makes lwIP suitable for use in embedded systems with tens
|
||||||
|
of kilobytes of free RAM and room for around 40 kilobytes
|
||||||
|
of code ROM.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
More information about lwIP can be found at the lwIP
|
||||||
|
homepage at <a
|
||||||
|
href="http://savannah.nongnu.org/projects/lwip/">http://savannah.nongnu.org/projects/lwip/</a>
|
||||||
|
or at the lwIP wiki at <a
|
||||||
|
href="http://lwip.wikia.com/">http://lwip.wikia.com/</a>.
|
||||||
|
</p>
|
||||||
|
</td><td>
|
||||||
|
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
298
ext/lwip/src/apps/httpd/fsdata.c
Executable file
298
ext/lwip/src/apps/httpd/fsdata.c
Executable file
@@ -0,0 +1,298 @@
|
|||||||
|
#include "lwip/apps/fs.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "fsdata.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define file_NULL (struct fsdata_file *) NULL
|
||||||
|
|
||||||
|
|
||||||
|
static const unsigned int dummy_align__img_sics_gif = 0;
|
||||||
|
static const unsigned char data__img_sics_gif[] = {
|
||||||
|
/* /img/sics.gif (14 chars) */
|
||||||
|
0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00,
|
||||||
|
|
||||||
|
/* HTTP header */
|
||||||
|
/* "HTTP/1.0 200 OK
|
||||||
|
" (17 bytes) */
|
||||||
|
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
|
||||||
|
0x0a,
|
||||||
|
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||||
|
" (63 bytes) */
|
||||||
|
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
|
||||||
|
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
|
||||||
|
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
|
||||||
|
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
|
||||||
|
/* "Content-type: image/gif
|
||||||
|
|
||||||
|
" (27 bytes) */
|
||||||
|
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d,
|
||||||
|
0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a,
|
||||||
|
/* raw file data (724 bytes) */
|
||||||
|
0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39,
|
||||||
|
0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6,
|
||||||
|
0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e,
|
||||||
|
0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99,
|
||||||
|
0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5,
|
||||||
|
0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b,
|
||||||
|
0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00,
|
||||||
|
0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f,
|
||||||
|
0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac,
|
||||||
|
0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31,
|
||||||
|
0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9,
|
||||||
|
0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51,
|
||||||
|
0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78,
|
||||||
|
0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0,
|
||||||
|
0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07,
|
||||||
|
0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42,
|
||||||
|
0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c,
|
||||||
|
0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01,
|
||||||
|
0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10,
|
||||||
|
0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8,
|
||||||
|
0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4,
|
||||||
|
0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86,
|
||||||
|
0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06,
|
||||||
|
0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07,
|
||||||
|
0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29,
|
||||||
|
0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a,
|
||||||
|
0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97,
|
||||||
|
0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9,
|
||||||
|
0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70,
|
||||||
|
0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c,
|
||||||
|
0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01,
|
||||||
|
0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24,
|
||||||
|
0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29,
|
||||||
|
0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73,
|
||||||
|
0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab,
|
||||||
|
0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45,
|
||||||
|
0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8,
|
||||||
|
0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5,
|
||||||
|
0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10,
|
||||||
|
0x41,0x00,0x00,0x3b,};
|
||||||
|
|
||||||
|
static const unsigned int dummy_align__404_html = 1;
|
||||||
|
static const unsigned char data__404_html[] = {
|
||||||
|
/* /404.html (10 chars) */
|
||||||
|
0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00,
|
||||||
|
|
||||||
|
/* HTTP header */
|
||||||
|
/* "HTTP/1.0 404 File not found
|
||||||
|
" (29 bytes) */
|
||||||
|
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c,
|
||||||
|
0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a,
|
||||||
|
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||||
|
" (63 bytes) */
|
||||||
|
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
|
||||||
|
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
|
||||||
|
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
|
||||||
|
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
|
||||||
|
/* "Content-type: text/html
|
||||||
|
|
||||||
|
" (27 bytes) */
|
||||||
|
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
|
||||||
|
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
|
||||||
|
/* raw file data (565 bytes) */
|
||||||
|
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
|
||||||
|
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
|
||||||
|
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
|
||||||
|
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
|
||||||
|
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
|
||||||
|
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
|
||||||
|
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
|
||||||
|
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
|
||||||
|
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
|
||||||
|
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
|
||||||
|
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
|
||||||
|
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
|
||||||
|
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
|
||||||
|
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
|
||||||
|
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
|
||||||
|
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
|
||||||
|
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
|
||||||
|
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
|
||||||
|
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
|
||||||
|
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
|
||||||
|
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
|
||||||
|
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
|
||||||
|
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
|
||||||
|
0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20,
|
||||||
|
0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a,
|
||||||
|
0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72,
|
||||||
|
0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,
|
||||||
|
0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20,
|
||||||
|
0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e,
|
||||||
|
0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,
|
||||||
|
0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
|
||||||
|
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
|
||||||
|
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
|
||||||
|
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
|
||||||
|
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
|
||||||
|
0x6d,0x6c,0x3e,0x0d,0x0a,};
|
||||||
|
|
||||||
|
static const unsigned int dummy_align__index_html = 2;
|
||||||
|
static const unsigned char data__index_html[] = {
|
||||||
|
/* /index.html (12 chars) */
|
||||||
|
0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00,
|
||||||
|
|
||||||
|
/* HTTP header */
|
||||||
|
/* "HTTP/1.0 200 OK
|
||||||
|
" (17 bytes) */
|
||||||
|
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
|
||||||
|
0x0a,
|
||||||
|
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||||
|
" (63 bytes) */
|
||||||
|
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
|
||||||
|
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
|
||||||
|
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
|
||||||
|
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
|
||||||
|
/* "Content-type: text/html
|
||||||
|
|
||||||
|
" (27 bytes) */
|
||||||
|
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
|
||||||
|
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
|
||||||
|
/* raw file data (1751 bytes) */
|
||||||
|
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
|
||||||
|
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
|
||||||
|
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
|
||||||
|
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
|
||||||
|
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
|
||||||
|
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
|
||||||
|
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
|
||||||
|
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
|
||||||
|
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
|
||||||
|
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
|
||||||
|
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
|
||||||
|
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
|
||||||
|
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
|
||||||
|
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
|
||||||
|
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
|
||||||
|
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
|
||||||
|
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
|
||||||
|
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
|
||||||
|
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
|
||||||
|
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
|
||||||
|
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
|
||||||
|
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
|
||||||
|
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
|
||||||
|
0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77,
|
||||||
|
0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20,
|
||||||
|
0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72,
|
||||||
|
0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20,
|
||||||
|
0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72,
|
||||||
|
0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20,
|
||||||
|
0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,
|
||||||
|
0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,
|
||||||
|
0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
|
||||||
|
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
|
||||||
|
0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c,
|
||||||
|
0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,
|
||||||
|
0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,
|
||||||
|
0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20,
|
||||||
|
0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,
|
||||||
|
0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50,
|
||||||
|
0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63,
|
||||||
|
0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61,
|
||||||
|
0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69,
|
||||||
|
0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,
|
||||||
|
0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,
|
||||||
|
0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,
|
||||||
|
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b,
|
||||||
|
0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,
|
||||||
|
0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75,
|
||||||
|
0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53,
|
||||||
|
0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e,
|
||||||
|
0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e,
|
||||||
|
0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c,
|
||||||
|
0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f,
|
||||||
|
0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20,
|
||||||
|
0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77,
|
||||||
|
0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65,
|
||||||
|
0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c,
|
||||||
|
0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70,
|
||||||
|
0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69,
|
||||||
|
0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20,
|
||||||
|
0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73,
|
||||||
|
0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61,
|
||||||
|
0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61,
|
||||||
|
0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77,
|
||||||
|
0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65,
|
||||||
|
0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,
|
||||||
|
0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75,
|
||||||
|
0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09,
|
||||||
|
0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,
|
||||||
|
0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f,
|
||||||
|
0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49,
|
||||||
|
0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,
|
||||||
|
0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09,
|
||||||
|
0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67,
|
||||||
|
0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61,
|
||||||
|
0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c,
|
||||||
|
0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,
|
||||||
|
0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69,
|
||||||
|
0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e,
|
||||||
|
0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,
|
||||||
|
0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20,
|
||||||
|
0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f,
|
||||||
|
0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72,
|
||||||
|
0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34,
|
||||||
|
0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20,
|
||||||
|
0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a,
|
||||||
|
0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,
|
||||||
|
0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,
|
||||||
|
0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49,
|
||||||
|
0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61,
|
||||||
|
0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,
|
||||||
|
0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d,
|
||||||
|
0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,
|
||||||
|
0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,
|
||||||
|
0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,
|
||||||
|
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,
|
||||||
|
0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,
|
||||||
|
0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f,
|
||||||
|
0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74,
|
||||||
|
0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61,
|
||||||
|
0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,
|
||||||
|
0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,
|
||||||
|
0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
|
||||||
|
0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c,
|
||||||
|
0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
|
||||||
|
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
|
||||||
|
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
|
||||||
|
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
|
||||||
|
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
|
||||||
|
0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const struct fsdata_file file__img_sics_gif[] = { {
|
||||||
|
file_NULL,
|
||||||
|
data__img_sics_gif,
|
||||||
|
data__img_sics_gif + 16,
|
||||||
|
sizeof(data__img_sics_gif) - 16,
|
||||||
|
1,
|
||||||
|
}};
|
||||||
|
|
||||||
|
const struct fsdata_file file__404_html[] = { {
|
||||||
|
file__img_sics_gif,
|
||||||
|
data__404_html,
|
||||||
|
data__404_html + 12,
|
||||||
|
sizeof(data__404_html) - 12,
|
||||||
|
1,
|
||||||
|
}};
|
||||||
|
|
||||||
|
const struct fsdata_file file__index_html[] = { {
|
||||||
|
file__404_html,
|
||||||
|
data__index_html,
|
||||||
|
data__index_html + 12,
|
||||||
|
sizeof(data__index_html) - 12,
|
||||||
|
1,
|
||||||
|
}};
|
||||||
|
|
||||||
|
#define FS_ROOT file__index_html
|
||||||
|
#define FS_NUMFILES 3
|
||||||
|
|
||||||
50
ext/lwip/src/apps/httpd/fsdata.h
Executable file
50
ext/lwip/src/apps/httpd/fsdata.h
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_FSDATA_H
|
||||||
|
#define LWIP_FSDATA_H
|
||||||
|
|
||||||
|
#include "lwip/apps/httpd_opts.h"
|
||||||
|
#include "lwip/apps/fs.h"
|
||||||
|
|
||||||
|
struct fsdata_file {
|
||||||
|
const struct fsdata_file *next;
|
||||||
|
const unsigned char *name;
|
||||||
|
const unsigned char *data;
|
||||||
|
int len;
|
||||||
|
u8_t flags;
|
||||||
|
#if HTTPD_PRECALCULATED_CHECKSUM
|
||||||
|
u16_t chksum_count;
|
||||||
|
const struct fsdata_chksum *chksum;
|
||||||
|
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LWIP_FSDATA_H */
|
||||||
2629
ext/lwip/src/apps/httpd/httpd.c
Executable file
2629
ext/lwip/src/apps/httpd/httpd.c
Executable file
File diff suppressed because it is too large
Load Diff
114
ext/lwip/src/apps/httpd/httpd_structs.h
Executable file
114
ext/lwip/src/apps/httpd/httpd_structs.h
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#ifndef LWIP_HTTPD_STRUCTS_H
|
||||||
|
#define LWIP_HTTPD_STRUCTS_H
|
||||||
|
|
||||||
|
#include "lwip/apps/httpd.h"
|
||||||
|
|
||||||
|
#if LWIP_HTTPD_DYNAMIC_HEADERS
|
||||||
|
/** This struct is used for a list of HTTP header strings for various
|
||||||
|
* filename extensions. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *extension;
|
||||||
|
const char *content_type;
|
||||||
|
} tHTTPHeader;
|
||||||
|
|
||||||
|
/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and
|
||||||
|
* RFC 2616 HTTP/1.1 for header field definitions) */
|
||||||
|
static const char * const g_psHTTPHeaderStrings[] =
|
||||||
|
{
|
||||||
|
"HTTP/1.0 200 OK\r\n",
|
||||||
|
"HTTP/1.0 404 File not found\r\n",
|
||||||
|
"HTTP/1.0 400 Bad Request\r\n",
|
||||||
|
"HTTP/1.0 501 Not Implemented\r\n",
|
||||||
|
"HTTP/1.1 200 OK\r\n",
|
||||||
|
"HTTP/1.1 404 File not found\r\n",
|
||||||
|
"HTTP/1.1 400 Bad Request\r\n",
|
||||||
|
"HTTP/1.1 501 Not Implemented\r\n",
|
||||||
|
"Content-Length: ",
|
||||||
|
"Connection: Close\r\n",
|
||||||
|
"Connection: keep-alive\r\n",
|
||||||
|
"Connection: keep-alive\r\nContent-Length: ",
|
||||||
|
"Server: "HTTPD_SERVER_AGENT"\r\n",
|
||||||
|
"\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
|
||||||
|
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||||
|
,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Indexes into the g_psHTTPHeaderStrings array */
|
||||||
|
#define HTTP_HDR_OK 0 /* 200 OK */
|
||||||
|
#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */
|
||||||
|
#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */
|
||||||
|
#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */
|
||||||
|
#define HTTP_HDR_OK_11 4 /* 200 OK */
|
||||||
|
#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */
|
||||||
|
#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */
|
||||||
|
#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */
|
||||||
|
#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/
|
||||||
|
#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */
|
||||||
|
#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */
|
||||||
|
#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/
|
||||||
|
#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */
|
||||||
|
#define DEFAULT_404_HTML 13 /* default 404 body */
|
||||||
|
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||||
|
#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n"
|
||||||
|
#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n"
|
||||||
|
#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n"
|
||||||
|
#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n"
|
||||||
|
#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n"
|
||||||
|
#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n"
|
||||||
|
#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n"
|
||||||
|
#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n"
|
||||||
|
#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n"
|
||||||
|
#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n"
|
||||||
|
#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n"
|
||||||
|
#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n"
|
||||||
|
#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n"
|
||||||
|
#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n"
|
||||||
|
#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n"
|
||||||
|
|
||||||
|
#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n"
|
||||||
|
|
||||||
|
/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES
|
||||||
|
* and http://www.iana.org/assignments/media-types for registered content types
|
||||||
|
* and subtypes) */
|
||||||
|
static const tHTTPHeader g_psHTTPHeaders[] =
|
||||||
|
{
|
||||||
|
{ "html", HTTP_HDR_HTML},
|
||||||
|
{ "htm", HTTP_HDR_HTML},
|
||||||
|
{ "shtml",HTTP_HDR_SSI},
|
||||||
|
{ "shtm", HTTP_HDR_SSI},
|
||||||
|
{ "ssi", HTTP_HDR_SSI},
|
||||||
|
{ "gif", HTTP_HDR_GIF},
|
||||||
|
{ "png", HTTP_HDR_PNG},
|
||||||
|
{ "jpg", HTTP_HDR_JPG},
|
||||||
|
{ "bmp", HTTP_HDR_BMP},
|
||||||
|
{ "ico", HTTP_HDR_ICO},
|
||||||
|
{ "class",HTTP_HDR_APP},
|
||||||
|
{ "cls", HTTP_HDR_APP},
|
||||||
|
{ "js", HTTP_HDR_JS},
|
||||||
|
{ "ram", HTTP_HDR_RA},
|
||||||
|
{ "css", HTTP_HDR_CSS},
|
||||||
|
{ "swf", HTTP_HDR_SWF},
|
||||||
|
{ "xml", HTTP_HDR_XML},
|
||||||
|
{ "xsl", HTTP_HDR_XML},
|
||||||
|
{ "pdf", HTTP_HDR_PDF},
|
||||||
|
{ "json", HTTP_HDR_JSON}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader))
|
||||||
|
|
||||||
|
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
|
||||||
|
|
||||||
|
#if LWIP_HTTPD_SSI
|
||||||
|
static const char * const g_pcSSIExtensions[] = {
|
||||||
|
".shtml", ".shtm", ".ssi", ".xml"
|
||||||
|
};
|
||||||
|
#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *))
|
||||||
|
#endif /* LWIP_HTTPD_SSI */
|
||||||
|
|
||||||
|
#endif /* LWIP_HTTPD_STRUCTS_H */
|
||||||
97
ext/lwip/src/apps/httpd/makefsdata/makefsdata
Executable file
97
ext/lwip/src/apps/httpd/makefsdata/makefsdata
Executable file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
open(OUTPUT, "> fsdata.c");
|
||||||
|
|
||||||
|
chdir("fs");
|
||||||
|
open(FILES, "find . -type f |");
|
||||||
|
|
||||||
|
while($file = <FILES>) {
|
||||||
|
|
||||||
|
# Do not include files in CVS directories nor backup files.
|
||||||
|
if($file =~ /(CVS|~)/) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
chop($file);
|
||||||
|
|
||||||
|
open(HEADER, "> /tmp/header") || die $!;
|
||||||
|
if($file =~ /404/) {
|
||||||
|
print(HEADER "HTTP/1.0 404 File not found\r\n");
|
||||||
|
} else {
|
||||||
|
print(HEADER "HTTP/1.0 200 OK\r\n");
|
||||||
|
}
|
||||||
|
print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n");
|
||||||
|
if($file =~ /\.html$/) {
|
||||||
|
print(HEADER "Content-type: text/html\r\n");
|
||||||
|
} elsif($file =~ /\.gif$/) {
|
||||||
|
print(HEADER "Content-type: image/gif\r\n");
|
||||||
|
} elsif($file =~ /\.png$/) {
|
||||||
|
print(HEADER "Content-type: image/png\r\n");
|
||||||
|
} elsif($file =~ /\.jpg$/) {
|
||||||
|
print(HEADER "Content-type: image/jpeg\r\n");
|
||||||
|
} elsif($file =~ /\.class$/) {
|
||||||
|
print(HEADER "Content-type: application/octet-stream\r\n");
|
||||||
|
} elsif($file =~ /\.ram$/) {
|
||||||
|
print(HEADER "Content-type: audio/x-pn-realaudio\r\n");
|
||||||
|
} else {
|
||||||
|
print(HEADER "Content-type: text/plain\r\n");
|
||||||
|
}
|
||||||
|
print(HEADER "\r\n");
|
||||||
|
close(HEADER);
|
||||||
|
|
||||||
|
unless($file =~ /\.plain$/ || $file =~ /cgi/) {
|
||||||
|
system("cat /tmp/header $file > /tmp/file");
|
||||||
|
} else {
|
||||||
|
system("cp $file /tmp/file");
|
||||||
|
}
|
||||||
|
|
||||||
|
open(FILE, "/tmp/file");
|
||||||
|
unlink("/tmp/file");
|
||||||
|
unlink("/tmp/header");
|
||||||
|
|
||||||
|
$file =~ s/\.//;
|
||||||
|
$fvar = $file;
|
||||||
|
$fvar =~ s-/-_-g;
|
||||||
|
$fvar =~ s-\.-_-g;
|
||||||
|
print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
|
||||||
|
print(OUTPUT "\t/* $file */\n\t");
|
||||||
|
for($j = 0; $j < length($file); $j++) {
|
||||||
|
printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
|
||||||
|
}
|
||||||
|
printf(OUTPUT "0,\n");
|
||||||
|
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
while(read(FILE, $data, 1)) {
|
||||||
|
if($i == 0) {
|
||||||
|
print(OUTPUT "\t");
|
||||||
|
}
|
||||||
|
printf(OUTPUT "%#02x, ", unpack("C", $data));
|
||||||
|
$i++;
|
||||||
|
if($i == 10) {
|
||||||
|
print(OUTPUT "\n");
|
||||||
|
$i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(OUTPUT "};\n\n");
|
||||||
|
close(FILE);
|
||||||
|
push(@fvars, $fvar);
|
||||||
|
push(@files, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
for($i = 0; $i < @fvars; $i++) {
|
||||||
|
$file = $files[$i];
|
||||||
|
$fvar = $fvars[$i];
|
||||||
|
|
||||||
|
if($i == 0) {
|
||||||
|
$prevfile = "NULL";
|
||||||
|
} else {
|
||||||
|
$prevfile = "file" . $fvars[$i - 1];
|
||||||
|
}
|
||||||
|
print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
|
||||||
|
print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
|
||||||
|
print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
|
||||||
|
print(OUTPUT "#define FS_NUMFILES $i\n");
|
||||||
1033
ext/lwip/src/apps/httpd/makefsdata/makefsdata.c
Executable file
1033
ext/lwip/src/apps/httpd/makefsdata/makefsdata.c
Executable file
File diff suppressed because it is too large
Load Diff
13
ext/lwip/src/apps/httpd/makefsdata/readme.txt
Executable file
13
ext/lwip/src/apps/httpd/makefsdata/readme.txt
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
This directory contains a script ('makefsdata') to create C code suitable for
|
||||||
|
httpd for given html pages (or other files) in a directory.
|
||||||
|
|
||||||
|
There is also a plain C console application doing the same and extended a bit.
|
||||||
|
|
||||||
|
Usage: htmlgen [targetdir] [-s] [-i]s
|
||||||
|
targetdir: relative or absolute path to files to convert
|
||||||
|
switch -s: toggle processing of subdirectories (default is on)
|
||||||
|
switch -e: exclude HTTP header from file (header is created at runtime, default is on)
|
||||||
|
switch -11: include HTTP 1.1 header (1.0 is default)
|
||||||
|
|
||||||
|
if targetdir not specified, makefsdata will attempt to
|
||||||
|
process files in subdirectory 'fs'.
|
||||||
661
ext/lwip/src/apps/lwiperf/lwiperf.c
Executable file
661
ext/lwip/src/apps/lwiperf/lwiperf.c
Executable file
@@ -0,0 +1,661 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* lwIP iPerf server implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup iperf Iperf server
|
||||||
|
* @ingroup apps
|
||||||
|
*
|
||||||
|
* This is a simple performance measuring server to check your bandwith using
|
||||||
|
* iPerf2 on a PC as client.
|
||||||
|
* It is currently a minimal implementation providing an IPv4 TCP server only.
|
||||||
|
*
|
||||||
|
* @todo: implement UDP mode and IPv6
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Simon Goldschmidt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Simon Goldschmidt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/lwiperf.h"
|
||||||
|
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
|
||||||
|
#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API
|
||||||
|
|
||||||
|
/** Specify the idle timeout (in seconds) after that the test fails */
|
||||||
|
#ifndef LWIPERF_TCP_MAX_IDLE_SEC
|
||||||
|
#define LWIPERF_TCP_MAX_IDLE_SEC 10U
|
||||||
|
#endif
|
||||||
|
#if LWIPERF_TCP_MAX_IDLE_SEC > 255
|
||||||
|
#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* File internal memory allocation (struct lwiperf_*): this defaults to
|
||||||
|
the heap */
|
||||||
|
#ifndef LWIPERF_ALLOC
|
||||||
|
#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type))
|
||||||
|
#define LWIPERF_FREE(type, item) mem_free(item)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** If this is 1, check that received data has the correct format */
|
||||||
|
#ifndef LWIPERF_CHECK_RX_DATA
|
||||||
|
#define LWIPERF_CHECK_RX_DATA 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** This is the Iperf settings struct sent from the client */
|
||||||
|
typedef struct _lwiperf_settings {
|
||||||
|
#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000
|
||||||
|
#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001
|
||||||
|
u32_t flags;
|
||||||
|
u32_t num_threads; /* unused for now */
|
||||||
|
u32_t remote_port;
|
||||||
|
u32_t buffer_len; /* unused for now */
|
||||||
|
u32_t win_band; /* TCP window / UDP rate: unused for now */
|
||||||
|
u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */
|
||||||
|
} lwiperf_settings_t;
|
||||||
|
|
||||||
|
/** Basic connection handle */
|
||||||
|
struct _lwiperf_state_base;
|
||||||
|
typedef struct _lwiperf_state_base lwiperf_state_base_t;
|
||||||
|
struct _lwiperf_state_base {
|
||||||
|
/* 1=tcp, 0=udp */
|
||||||
|
u8_t tcp;
|
||||||
|
/* 1=server, 0=client */
|
||||||
|
u8_t server;
|
||||||
|
lwiperf_state_base_t* next;
|
||||||
|
lwiperf_state_base_t* related_server_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Connection handle for a TCP iperf session */
|
||||||
|
typedef struct _lwiperf_state_tcp {
|
||||||
|
lwiperf_state_base_t base;
|
||||||
|
struct tcp_pcb* server_pcb;
|
||||||
|
struct tcp_pcb* conn_pcb;
|
||||||
|
u32_t time_started;
|
||||||
|
lwiperf_report_fn report_fn;
|
||||||
|
void* report_arg;
|
||||||
|
u8_t poll_count;
|
||||||
|
u8_t next_num;
|
||||||
|
u32_t bytes_transferred;
|
||||||
|
lwiperf_settings_t settings;
|
||||||
|
u8_t have_settings_buf;
|
||||||
|
} lwiperf_state_tcp_t;
|
||||||
|
|
||||||
|
/** List of active iperf sessions */
|
||||||
|
static lwiperf_state_base_t* lwiperf_all_connections;
|
||||||
|
/** A const buffer to send from: we want to measure sending, not copying! */
|
||||||
|
static const u8_t lwiperf_txbuf_const[1600] = {
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
|
||||||
|
};
|
||||||
|
|
||||||
|
static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb);
|
||||||
|
static void lwiperf_tcp_err(void *arg, err_t err);
|
||||||
|
|
||||||
|
/** Add an iperf session to the 'active' list */
|
||||||
|
static void
|
||||||
|
lwiperf_list_add(lwiperf_state_base_t* item)
|
||||||
|
{
|
||||||
|
if (lwiperf_all_connections == NULL) {
|
||||||
|
lwiperf_all_connections = item;
|
||||||
|
} else {
|
||||||
|
item = lwiperf_all_connections;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove an iperf session from the 'active' list */
|
||||||
|
static void
|
||||||
|
lwiperf_list_remove(lwiperf_state_base_t* item)
|
||||||
|
{
|
||||||
|
lwiperf_state_base_t* prev = NULL;
|
||||||
|
lwiperf_state_base_t* iter;
|
||||||
|
for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) {
|
||||||
|
if (iter == item) {
|
||||||
|
if (prev == NULL) {
|
||||||
|
lwiperf_all_connections = iter->next;
|
||||||
|
} else {
|
||||||
|
prev->next = item;
|
||||||
|
}
|
||||||
|
/* @debug: ensure this item is listed only once */
|
||||||
|
for (iter = iter->next; iter != NULL; iter = iter->next) {
|
||||||
|
LWIP_ASSERT("duplicate entry", iter != item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Call the report function of an iperf tcp session */
|
||||||
|
static void
|
||||||
|
lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
|
||||||
|
{
|
||||||
|
if ((conn != NULL) && (conn->report_fn != NULL)) {
|
||||||
|
u32_t now, duration_ms, bandwidth_kbitpsec;
|
||||||
|
now = sys_now();
|
||||||
|
duration_ms = now - conn->time_started;
|
||||||
|
if (duration_ms == 0) {
|
||||||
|
bandwidth_kbitpsec = 0;
|
||||||
|
} else {
|
||||||
|
bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U;
|
||||||
|
}
|
||||||
|
conn->report_fn(conn->report_arg, report_type,
|
||||||
|
&conn->conn_pcb->local_ip, conn->conn_pcb->local_port,
|
||||||
|
&conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port,
|
||||||
|
conn->bytes_transferred, duration_ms, bandwidth_kbitpsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close an iperf tcp session */
|
||||||
|
static void
|
||||||
|
lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
lwip_tcp_conn_report(conn, report_type);
|
||||||
|
lwiperf_list_remove(&conn->base);
|
||||||
|
if (conn->conn_pcb != NULL) {
|
||||||
|
tcp_arg(conn->conn_pcb, NULL);
|
||||||
|
tcp_poll(conn->conn_pcb, NULL, 0);
|
||||||
|
tcp_sent(conn->conn_pcb, NULL);
|
||||||
|
tcp_recv(conn->conn_pcb, NULL);
|
||||||
|
tcp_err(conn->conn_pcb, NULL);
|
||||||
|
err = tcp_close(conn->conn_pcb);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
/* don't want to wait for free memory here... */
|
||||||
|
tcp_abort(conn->conn_pcb);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no conn pcb, this is the server pcb */
|
||||||
|
err = tcp_close(conn->server_pcb);
|
||||||
|
LWIP_ASSERT("error", err != ERR_OK);
|
||||||
|
}
|
||||||
|
LWIPERF_FREE(lwiperf_state_tcp_t, conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Try to send more data on an iperf tcp session */
|
||||||
|
static err_t
|
||||||
|
lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
|
||||||
|
{
|
||||||
|
int send_more;
|
||||||
|
err_t err;
|
||||||
|
u16_t txlen;
|
||||||
|
u16_t txlen_max;
|
||||||
|
void* txptr;
|
||||||
|
u8_t apiflags;
|
||||||
|
|
||||||
|
LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));
|
||||||
|
|
||||||
|
do {
|
||||||
|
send_more = 0;
|
||||||
|
if (conn->settings.amount & PP_HTONL(0x80000000)) {
|
||||||
|
/* 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)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 */
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* this session is byte-limited */
|
||||||
|
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 */
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->bytes_transferred < 24) {
|
||||||
|
/* transmit the settings a first time */
|
||||||
|
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred];
|
||||||
|
txlen_max = (u16_t)(24 - conn->bytes_transferred);
|
||||||
|
apiflags = TCP_WRITE_FLAG_COPY;
|
||||||
|
} else if (conn->bytes_transferred < 48) {
|
||||||
|
/* transmit the settings a second time */
|
||||||
|
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24];
|
||||||
|
txlen_max = (u16_t)(48 - conn->bytes_transferred);
|
||||||
|
apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
|
||||||
|
send_more = 1;
|
||||||
|
} else {
|
||||||
|
/* transmit data */
|
||||||
|
/* @todo: every x bytes, transmit the settings again */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
apiflags = 0; /* no copying needed */
|
||||||
|
send_more = 1;
|
||||||
|
}
|
||||||
|
txlen = txlen_max;
|
||||||
|
do {
|
||||||
|
err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
|
||||||
|
if (err == ERR_MEM) {
|
||||||
|
txlen /= 2;
|
||||||
|
}
|
||||||
|
} while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2)));
|
||||||
|
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
conn->bytes_transferred += txlen;
|
||||||
|
} else {
|
||||||
|
send_more = 0;
|
||||||
|
}
|
||||||
|
} while(send_more);
|
||||||
|
|
||||||
|
tcp_output(conn->conn_pcb);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TCP sent callback, try to send more data */
|
||||||
|
static err_t
|
||||||
|
lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
|
||||||
|
{
|
||||||
|
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
|
||||||
|
/* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */
|
||||||
|
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
|
||||||
|
LWIP_UNUSED_ARG(tpcb);
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
|
||||||
|
conn->poll_count = 0;
|
||||||
|
|
||||||
|
return lwiperf_tcp_client_send_more(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TCP connected callback (active connection), send data now */
|
||||||
|
static err_t
|
||||||
|
lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
|
||||||
|
{
|
||||||
|
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
|
||||||
|
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
|
||||||
|
LWIP_UNUSED_ARG(tpcb);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
conn->poll_count = 0;
|
||||||
|
conn->time_started = sys_now();
|
||||||
|
return lwiperf_tcp_client_send_more(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Start TCP connection back to the client (either parallel or after the
|
||||||
|
* receive test has finished.
|
||||||
|
*/
|
||||||
|
static err_t
|
||||||
|
lwiperf_tx_start(lwiperf_state_tcp_t* conn)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
lwiperf_state_tcp_t* client_conn;
|
||||||
|
struct tcp_pcb* newpcb;
|
||||||
|
ip_addr_t remote_addr;
|
||||||
|
u16_t remote_port;
|
||||||
|
|
||||||
|
client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
|
||||||
|
if (client_conn == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
newpcb = tcp_new();
|
||||||
|
if (newpcb == NULL) {
|
||||||
|
LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t));
|
||||||
|
client_conn->base.server = 0;
|
||||||
|
client_conn->server_pcb = NULL;
|
||||||
|
client_conn->conn_pcb = newpcb;
|
||||||
|
client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */
|
||||||
|
client_conn->poll_count = 0;
|
||||||
|
client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
|
||||||
|
client_conn->bytes_transferred = 0;
|
||||||
|
client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */
|
||||||
|
|
||||||
|
tcp_arg(newpcb, client_conn);
|
||||||
|
tcp_sent(newpcb, lwiperf_tcp_client_sent);
|
||||||
|
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
|
||||||
|
tcp_err(newpcb, lwiperf_tcp_err);
|
||||||
|
|
||||||
|
ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
|
||||||
|
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) {
|
||||||
|
lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
lwiperf_list_add(&client_conn->base);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Receive data on an iperf tcp session */
|
||||||
|
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;
|
||||||
|
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
|
||||||
|
|
||||||
|
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
|
||||||
|
LWIP_UNUSED_ARG(tpcb);
|
||||||
|
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
if (p == NULL) {
|
||||||
|
/* connection closed -> test done */
|
||||||
|
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
|
||||||
|
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
|
||||||
|
/* client requested transmission after end of test */
|
||||||
|
lwiperf_tx_start(conn);
|
||||||
|
}
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
tot_len = p->tot_len;
|
||||||
|
|
||||||
|
conn->poll_count = 0;
|
||||||
|
|
||||||
|
if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) {
|
||||||
|
/* wait for 24-byte header */
|
||||||
|
if (p->tot_len < sizeof(lwiperf_settings_t)) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
if (!conn->have_settings_buf) {
|
||||||
|
if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
conn->have_settings_buf = 1;
|
||||||
|
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
|
||||||
|
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) {
|
||||||
|
/* client requested parallel transmission test */
|
||||||
|
err_t err2 = lwiperf_tx_start(conn);
|
||||||
|
if (err2 != ERR_OK) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR);
|
||||||
|
pbuf_free(p);
|
||||||
|
return err2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn->bytes_transferred += sizeof(lwiperf_settings_t);
|
||||||
|
if (conn->bytes_transferred <= 24) {
|
||||||
|
conn->time_started = sys_now();
|
||||||
|
tcp_recved(tpcb, p->tot_len);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
conn->next_num = 4; /* 24 bytes received... */
|
||||||
|
tmp = pbuf_header(p, -24);
|
||||||
|
LWIP_ASSERT("pbuf_header failed", tmp == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_idx = 0;
|
||||||
|
for (q = p; q != NULL; q = q->next) {
|
||||||
|
#if LWIPERF_CHECK_RX_DATA
|
||||||
|
const u8_t* payload = (const u8_t*)q->payload;
|
||||||
|
u16_t i;
|
||||||
|
for (i = 0; i < q->len; i++) {
|
||||||
|
u8_t val = payload[i];
|
||||||
|
u8_t num = val - '0';
|
||||||
|
if (num == conn->next_num) {
|
||||||
|
conn->next_num++;
|
||||||
|
if (conn->next_num == 10) {
|
||||||
|
conn->next_num = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
packet_idx += q->len;
|
||||||
|
}
|
||||||
|
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
|
||||||
|
conn->bytes_transferred += packet_idx;
|
||||||
|
tcp_recved(tpcb, tot_len);
|
||||||
|
pbuf_free(p);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Error callback, iperf tcp session aborted */
|
||||||
|
static void
|
||||||
|
lwiperf_tcp_err(void *arg, err_t err)
|
||||||
|
{
|
||||||
|
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
|
||||||
|
LWIP_UNUSED_ARG(err);
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TCP poll callback, try to send more data */
|
||||||
|
static err_t
|
||||||
|
lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb)
|
||||||
|
{
|
||||||
|
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
|
||||||
|
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
|
||||||
|
LWIP_UNUSED_ARG(tpcb);
|
||||||
|
if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) {
|
||||||
|
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
|
||||||
|
return ERR_OK; /* lwiperf_tcp_close frees conn */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conn->base.server) {
|
||||||
|
lwiperf_tcp_client_send_more(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This is called when a new client connects for an iperf tcp session */
|
||||||
|
static err_t
|
||||||
|
lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||||
|
{
|
||||||
|
lwiperf_state_tcp_t *s, *conn;
|
||||||
|
if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) {
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = (lwiperf_state_tcp_t*)arg;
|
||||||
|
conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
|
||||||
|
if (conn == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
memset(conn, 0, sizeof(lwiperf_state_tcp_t));
|
||||||
|
conn->base.tcp = 1;
|
||||||
|
conn->base.server = 1;
|
||||||
|
conn->base.related_server_state = &s->base;
|
||||||
|
conn->server_pcb = s->server_pcb;
|
||||||
|
conn->conn_pcb = newpcb;
|
||||||
|
conn->time_started = sys_now();
|
||||||
|
conn->report_fn = s->report_fn;
|
||||||
|
conn->report_arg = s->report_arg;
|
||||||
|
|
||||||
|
/* setup the tcp rx connection */
|
||||||
|
tcp_arg(newpcb, conn);
|
||||||
|
tcp_recv(newpcb, lwiperf_tcp_recv);
|
||||||
|
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
|
||||||
|
tcp_err(conn->conn_pcb, lwiperf_tcp_err);
|
||||||
|
|
||||||
|
lwiperf_list_add(&conn->base);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iperf
|
||||||
|
* Start a TCP iperf server on the default TCP port (5001) and listen for
|
||||||
|
* incoming connections from iperf clients.
|
||||||
|
*
|
||||||
|
* @returns a connection handle that can be used to abort the server
|
||||||
|
* by calling @ref lwiperf_abort()
|
||||||
|
*/
|
||||||
|
void*
|
||||||
|
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
|
||||||
|
{
|
||||||
|
return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
|
||||||
|
report_fn, report_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iperf
|
||||||
|
* Start a TCP iperf server on a specific IP address and port and listen for
|
||||||
|
* incoming connections from iperf clients.
|
||||||
|
*
|
||||||
|
* @returns a connection handle that can be used to abort the server
|
||||||
|
* by calling @ref lwiperf_abort()
|
||||||
|
*/
|
||||||
|
void*
|
||||||
|
lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port,
|
||||||
|
lwiperf_report_fn report_fn, void* report_arg)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
struct tcp_pcb* pcb;
|
||||||
|
lwiperf_state_tcp_t* s;
|
||||||
|
|
||||||
|
if (local_addr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
|
||||||
|
if (s == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof(lwiperf_state_tcp_t));
|
||||||
|
s->base.tcp = 1;
|
||||||
|
s->base.server = 1;
|
||||||
|
s->report_fn = report_fn;
|
||||||
|
s->report_arg = report_arg;
|
||||||
|
|
||||||
|
pcb = tcp_new();
|
||||||
|
if (pcb != NULL) {
|
||||||
|
err = tcp_bind(pcb, local_addr, local_port);
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
s->server_pcb = tcp_listen_with_backlog(pcb, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->server_pcb == NULL) {
|
||||||
|
if (pcb != NULL) {
|
||||||
|
tcp_close(pcb);
|
||||||
|
}
|
||||||
|
LWIPERF_FREE(lwiperf_state_tcp_t, s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pcb = NULL;
|
||||||
|
|
||||||
|
tcp_arg(s->server_pcb, s);
|
||||||
|
tcp_accept(s->server_pcb, lwiperf_tcp_accept);
|
||||||
|
|
||||||
|
lwiperf_list_add(&s->base);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iperf
|
||||||
|
* Abort an iperf session (handle returned by lwiperf_start_tcp_server*())
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lwiperf_abort(void* lwiperf_session)
|
||||||
|
{
|
||||||
|
lwiperf_state_base_t* i, *dealloc, *last = NULL;
|
||||||
|
|
||||||
|
for (i = lwiperf_all_connections; i != NULL; ) {
|
||||||
|
if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) {
|
||||||
|
dealloc = i;
|
||||||
|
i = i->next;
|
||||||
|
if (last != NULL) {
|
||||||
|
last->next = i;
|
||||||
|
}
|
||||||
|
LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */
|
||||||
|
} else {
|
||||||
|
last = i;
|
||||||
|
i = i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */
|
||||||
2028
ext/lwip/src/apps/mdns/mdns.c
Executable file
2028
ext/lwip/src/apps/mdns/mdns.c
Executable file
File diff suppressed because it is too large
Load Diff
1341
ext/lwip/src/apps/mqtt/mqtt.c
Executable file
1341
ext/lwip/src/apps/mqtt/mqtt.c
Executable file
File diff suppressed because it is too large
Load Diff
367
ext/lwip/src/apps/netbiosns/netbiosns.c
Executable file
367
ext/lwip/src/apps/netbiosns/netbiosns.c
Executable file
@@ -0,0 +1,367 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* NetBIOS name service responder
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup netbiosns NETBIOS responder
|
||||||
|
* @ingroup apps
|
||||||
|
*
|
||||||
|
* This is an example implementation of a NetBIOS name server.
|
||||||
|
* It responds to name queries for a configurable name.
|
||||||
|
* Name resolving is not supported.
|
||||||
|
*
|
||||||
|
* Note that the device doesn't broadcast it's own name so can't
|
||||||
|
* detect duplicate names!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/netbiosns.h"
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/** default port number for "NetBIOS Name service */
|
||||||
|
#define NETBIOS_PORT 137
|
||||||
|
|
||||||
|
/** size of a NetBIOS name */
|
||||||
|
#define NETBIOS_NAME_LEN 16
|
||||||
|
|
||||||
|
/** The Time-To-Live for NetBIOS name responds (in seconds)
|
||||||
|
* Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
|
||||||
|
#define NETBIOS_NAME_TTL 300000u
|
||||||
|
|
||||||
|
/** NetBIOS header flags */
|
||||||
|
#define NETB_HFLAG_RESPONSE 0x8000U
|
||||||
|
#define NETB_HFLAG_OPCODE 0x7800U
|
||||||
|
#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U
|
||||||
|
#define NETB_HFLAG_AUTHORATIVE 0x0400U
|
||||||
|
#define NETB_HFLAG_TRUNCATED 0x0200U
|
||||||
|
#define NETB_HFLAG_RECURS_DESIRED 0x0100U
|
||||||
|
#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U
|
||||||
|
#define NETB_HFLAG_BROADCAST 0x0010U
|
||||||
|
#define NETB_HFLAG_REPLYCODE 0x0008U
|
||||||
|
#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U
|
||||||
|
|
||||||
|
/** NetBIOS name flags */
|
||||||
|
#define NETB_NFLAG_UNIQUE 0x8000U
|
||||||
|
#define NETB_NFLAG_NODETYPE 0x6000U
|
||||||
|
#define NETB_NFLAG_NODETYPE_HNODE 0x6000U
|
||||||
|
#define NETB_NFLAG_NODETYPE_MNODE 0x4000U
|
||||||
|
#define NETB_NFLAG_NODETYPE_PNODE 0x2000U
|
||||||
|
#define NETB_NFLAG_NODETYPE_BNODE 0x0000U
|
||||||
|
|
||||||
|
/** NetBIOS message header */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct netbios_hdr {
|
||||||
|
PACK_STRUCT_FIELD(u16_t trans_id);
|
||||||
|
PACK_STRUCT_FIELD(u16_t flags);
|
||||||
|
PACK_STRUCT_FIELD(u16_t questions);
|
||||||
|
PACK_STRUCT_FIELD(u16_t answerRRs);
|
||||||
|
PACK_STRUCT_FIELD(u16_t authorityRRs);
|
||||||
|
PACK_STRUCT_FIELD(u16_t additionalRRs);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** NetBIOS message name part */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct netbios_name_hdr {
|
||||||
|
PACK_STRUCT_FLD_8(u8_t nametype);
|
||||||
|
PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]);
|
||||||
|
PACK_STRUCT_FIELD(u16_t type);
|
||||||
|
PACK_STRUCT_FIELD(u16_t cls);
|
||||||
|
PACK_STRUCT_FIELD(u32_t ttl);
|
||||||
|
PACK_STRUCT_FIELD(u16_t datalen);
|
||||||
|
PACK_STRUCT_FIELD(u16_t flags);
|
||||||
|
PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** NetBIOS message */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct netbios_resp
|
||||||
|
{
|
||||||
|
struct netbios_hdr resp_hdr;
|
||||||
|
struct netbios_name_hdr resp_name;
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NETBIOS_LWIP_NAME
|
||||||
|
#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
|
||||||
|
#else
|
||||||
|
static char netbiosns_local_name[NETBIOS_NAME_LEN];
|
||||||
|
#define NETBIOS_LOCAL_NAME netbiosns_local_name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct udp_pcb *netbiosns_pcb;
|
||||||
|
|
||||||
|
/** Decode a NetBIOS name (from packet to string) */
|
||||||
|
static int
|
||||||
|
netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
|
||||||
|
{
|
||||||
|
char *pname;
|
||||||
|
char cname;
|
||||||
|
char cnbname;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(name_dec_len);
|
||||||
|
|
||||||
|
/* Start decoding netbios name. */
|
||||||
|
pname = name_enc;
|
||||||
|
for (;;) {
|
||||||
|
/* Every two characters of the first level-encoded name
|
||||||
|
* turn into one character in the decoded name. */
|
||||||
|
cname = *pname;
|
||||||
|
if (cname == '\0')
|
||||||
|
break; /* no more characters */
|
||||||
|
if (cname == '.')
|
||||||
|
break; /* scope ID follows */
|
||||||
|
if (cname < 'A' || cname > 'Z') {
|
||||||
|
/* Not legal. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cname -= 'A';
|
||||||
|
cnbname = cname << 4;
|
||||||
|
pname++;
|
||||||
|
|
||||||
|
cname = *pname;
|
||||||
|
if (cname == '\0' || cname == '.') {
|
||||||
|
/* No more characters in the name - but we're in
|
||||||
|
* the middle of a pair. Not legal. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (cname < 'A' || cname > 'Z') {
|
||||||
|
/* Not legal. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cname -= 'A';
|
||||||
|
cnbname |= cname;
|
||||||
|
pname++;
|
||||||
|
|
||||||
|
/* Do we have room to store the character? */
|
||||||
|
if (idx < NETBIOS_NAME_LEN) {
|
||||||
|
/* Yes - store the character. */
|
||||||
|
name_dec[idx++] = (cnbname!=' '?cnbname:'\0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* function currently unused */
|
||||||
|
/** Encode a NetBIOS name (from string to packet) - currently unused because
|
||||||
|
we don't ask for names. */
|
||||||
|
static int
|
||||||
|
netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
|
||||||
|
{
|
||||||
|
char *pname;
|
||||||
|
char cname;
|
||||||
|
unsigned char ucname;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
/* Start encoding netbios name. */
|
||||||
|
pname = name_enc;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/* Every two characters of the first level-encoded name
|
||||||
|
* turn into one character in the decoded name. */
|
||||||
|
cname = *pname;
|
||||||
|
if (cname == '\0')
|
||||||
|
break; /* no more characters */
|
||||||
|
if (cname == '.')
|
||||||
|
break; /* scope ID follows */
|
||||||
|
if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
|
||||||
|
/* Not legal. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we have room to store the character? */
|
||||||
|
if (idx >= name_dec_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yes - store the character. */
|
||||||
|
ucname = cname;
|
||||||
|
name_dec[idx++] = ('A'+((ucname>>4) & 0x0F));
|
||||||
|
name_dec[idx++] = ('A'+( ucname & 0x0F));
|
||||||
|
pname++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill with "space" coding */
|
||||||
|
for (;idx < name_dec_len - 1;) {
|
||||||
|
name_dec[idx++] = 'C';
|
||||||
|
name_dec[idx++] = 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate string */
|
||||||
|
name_dec[idx] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
/** NetBIOS Name service recv callback */
|
||||||
|
static void
|
||||||
|
netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
/* if packet is valid */
|
||||||
|
if (p != NULL) {
|
||||||
|
char netbios_name[NETBIOS_NAME_LEN+1];
|
||||||
|
struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload;
|
||||||
|
struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1);
|
||||||
|
|
||||||
|
/* we only answer if we got a default interface */
|
||||||
|
if (netif_default != NULL) {
|
||||||
|
/* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
|
||||||
|
/* if the packet is a NetBIOS name query question */
|
||||||
|
if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
|
||||||
|
((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
|
||||||
|
(netbios_hdr->questions == PP_NTOHS(1))) {
|
||||||
|
/* decode the NetBIOS name */
|
||||||
|
netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
|
||||||
|
/* if the packet is for us */
|
||||||
|
if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
|
||||||
|
struct pbuf *q;
|
||||||
|
struct netbios_resp *resp;
|
||||||
|
|
||||||
|
q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
|
||||||
|
if (q != NULL) {
|
||||||
|
resp = (struct netbios_resp*)q->payload;
|
||||||
|
|
||||||
|
/* prepare NetBIOS header response */
|
||||||
|
resp->resp_hdr.trans_id = netbios_hdr->trans_id;
|
||||||
|
resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE |
|
||||||
|
NETB_HFLAG_OPCODE_NAME_QUERY |
|
||||||
|
NETB_HFLAG_AUTHORATIVE |
|
||||||
|
NETB_HFLAG_RECURS_DESIRED);
|
||||||
|
resp->resp_hdr.questions = 0;
|
||||||
|
resp->resp_hdr.answerRRs = PP_HTONS(1);
|
||||||
|
resp->resp_hdr.authorityRRs = 0;
|
||||||
|
resp->resp_hdr.additionalRRs = 0;
|
||||||
|
|
||||||
|
/* prepare NetBIOS header datas */
|
||||||
|
MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
|
||||||
|
resp->resp_name.nametype = netbios_name_hdr->nametype;
|
||||||
|
resp->resp_name.type = netbios_name_hdr->type;
|
||||||
|
resp->resp_name.cls = netbios_name_hdr->cls;
|
||||||
|
resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL);
|
||||||
|
resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr));
|
||||||
|
resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
|
||||||
|
ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
|
||||||
|
|
||||||
|
/* send the NetBIOS response */
|
||||||
|
udp_sendto(upcb, q, addr, port);
|
||||||
|
|
||||||
|
/* free the "reference" pbuf */
|
||||||
|
pbuf_free(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* free the pbuf */
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup netbiosns
|
||||||
|
* Init netbios responder
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
netbiosns_init(void)
|
||||||
|
{
|
||||||
|
#ifdef NETBIOS_LWIP_NAME
|
||||||
|
LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||||
|
if (netbiosns_pcb != NULL) {
|
||||||
|
/* we have to be allowed to send broadcast packets! */
|
||||||
|
ip_set_option(netbiosns_pcb, SOF_BROADCAST);
|
||||||
|
udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
|
||||||
|
udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NETBIOS_LWIP_NAME
|
||||||
|
/**
|
||||||
|
* @ingroup netbiosns
|
||||||
|
* Set netbios name. ATTENTION: the hostname must be less than 15 characters!
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
netbiosns_set_name(const char* hostname)
|
||||||
|
{
|
||||||
|
size_t copy_len = strlen(hostname);
|
||||||
|
LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
|
||||||
|
if (copy_len >= NETBIOS_NAME_LEN) {
|
||||||
|
copy_len = NETBIOS_NAME_LEN - 1;
|
||||||
|
}
|
||||||
|
MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup netbiosns
|
||||||
|
* Stop netbios responder
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
netbiosns_stop(void)
|
||||||
|
{
|
||||||
|
if (netbiosns_pcb != NULL) {
|
||||||
|
udp_remove(netbiosns_pcb);
|
||||||
|
netbiosns_pcb = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_UDP */
|
||||||
749
ext/lwip/src/apps/snmp/snmp_asn1.c
Executable file
749
ext/lwip/src/apps/snmp/snmp_asn1.c
Executable file
@@ -0,0 +1,749 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Abstract Syntax Notation One (ISO 8824, 8825) encoding
|
||||||
|
*
|
||||||
|
* @todo not optimised (yet), favor correctness over speed, favor speed over size
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
* Martin Hentschel <info@cl-soft.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "snmp_asn1.h"
|
||||||
|
|
||||||
|
#define PBUF_OP_EXEC(code) \
|
||||||
|
if ((code) != ERR_OK) { \
|
||||||
|
return ERR_BUF; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a TLV into a pbuf stream.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param tlv TLV to encode
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv)
|
||||||
|
{
|
||||||
|
u8_t data;
|
||||||
|
u8_t length_bytes_required;
|
||||||
|
|
||||||
|
/* write type */
|
||||||
|
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) {
|
||||||
|
/* extended format is not used by SNMP so we do not accept those values */
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if (tlv->type_len != 0) {
|
||||||
|
/* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type));
|
||||||
|
tlv->type_len = 1;
|
||||||
|
|
||||||
|
/* write length */
|
||||||
|
if (tlv->value_len <= 127) {
|
||||||
|
length_bytes_required = 1;
|
||||||
|
} else if (tlv->value_len <= 255) {
|
||||||
|
length_bytes_required = 2;
|
||||||
|
} else {
|
||||||
|
length_bytes_required = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for forced min length */
|
||||||
|
if (tlv->length_len > 0) {
|
||||||
|
if (tlv->length_len < length_bytes_required) {
|
||||||
|
/* unable to code requested length in requested number of bytes */
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
length_bytes_required = tlv->length_len;
|
||||||
|
} else {
|
||||||
|
tlv->length_len = length_bytes_required;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length_bytes_required > 1) {
|
||||||
|
/* multi byte representation required */
|
||||||
|
length_bytes_required--;
|
||||||
|
data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */
|
||||||
|
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
|
||||||
|
|
||||||
|
while (length_bytes_required > 1) {
|
||||||
|
if (length_bytes_required == 2) {
|
||||||
|
/* append high byte */
|
||||||
|
data = (u8_t)(tlv->value_len >> 8);
|
||||||
|
} else {
|
||||||
|
/* append leading 0x00 */
|
||||||
|
data = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
|
||||||
|
length_bytes_required--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append low byte */
|
||||||
|
data = (u8_t)(tlv->value_len & 0xFF);
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param raw_len raw data length
|
||||||
|
* @param raw points raw data
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len)
|
||||||
|
{
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len));
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt())
|
||||||
|
* @param value is the host order u32_t value to be encoded
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*
|
||||||
|
* @see snmp_asn1_enc_u32t_cnt()
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value)
|
||||||
|
{
|
||||||
|
if (octets_needed > 5) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if (octets_needed == 5) {
|
||||||
|
/* not enough bits in 'value' add leading 0x00 */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00));
|
||||||
|
octets_needed--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (octets_needed > 1) {
|
||||||
|
octets_needed--;
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (only) one least significant octet */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value));
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes u64_t (counter64) into a pbuf chained ASN1 msg.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt())
|
||||||
|
* @param value is the host order u32_t value to be encoded
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*
|
||||||
|
* @see snmp_asn1_enc_u64t_cnt()
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value)
|
||||||
|
{
|
||||||
|
if (octets_needed > 9) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if (octets_needed == 9) {
|
||||||
|
/* not enough bits in 'value' add leading 0x00 */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00));
|
||||||
|
octets_needed--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (octets_needed > 4) {
|
||||||
|
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))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always write at least one octet (also in case of value == 0) */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value)));
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes s32_t integer into a pbuf chained ASN1 msg.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt())
|
||||||
|
* @param value is the host order s32_t value to be encoded
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*
|
||||||
|
* @see snmp_asn1_enc_s32t_cnt()
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value)
|
||||||
|
{
|
||||||
|
while (octets_needed > 1) {
|
||||||
|
octets_needed--;
|
||||||
|
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (only) one least significant octet */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value));
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes object identifier into a pbuf chained ASN1 msg.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param oid points to object identifier array
|
||||||
|
* @param oid_len object identifier array length
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len)
|
||||||
|
{
|
||||||
|
if (oid_len > 1) {
|
||||||
|
/* write compressed first two sub id's */
|
||||||
|
u32_t compressed_byte = ((oid[0] * 40) + oid[1]);
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte));
|
||||||
|
oid_len -= 2;
|
||||||
|
oid += 2;
|
||||||
|
} else {
|
||||||
|
/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */
|
||||||
|
/* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (oid_len > 0) {
|
||||||
|
u32_t sub_id;
|
||||||
|
u8_t shift, tail;
|
||||||
|
|
||||||
|
oid_len--;
|
||||||
|
sub_id = *oid;
|
||||||
|
tail = 0;
|
||||||
|
shift = 28;
|
||||||
|
while (shift > 0) {
|
||||||
|
u8_t code;
|
||||||
|
|
||||||
|
code = (u8_t)(sub_id >> shift);
|
||||||
|
if ((code != 0) || (tail != 0)) {
|
||||||
|
tail = 1;
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80));
|
||||||
|
}
|
||||||
|
shift -= 7;
|
||||||
|
}
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F));
|
||||||
|
|
||||||
|
/* proceed to next sub-identifier */
|
||||||
|
oid++;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns octet count for length.
|
||||||
|
*
|
||||||
|
* @param length parameter length
|
||||||
|
* @param octets_needed points to the return value
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
|
||||||
|
{
|
||||||
|
if (length < 0x80U) {
|
||||||
|
*octets_needed = 1;
|
||||||
|
} else if (length < 0x100U) {
|
||||||
|
*octets_needed = 2;
|
||||||
|
} else {
|
||||||
|
*octets_needed = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns octet count for an u32_t.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||||
|
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
|
||||||
|
{
|
||||||
|
if (value < 0x80UL) {
|
||||||
|
*octets_needed = 1;
|
||||||
|
} else if (value < 0x8000UL) {
|
||||||
|
*octets_needed = 2;
|
||||||
|
} else if (value < 0x800000UL) {
|
||||||
|
*octets_needed = 3;
|
||||||
|
} else if (value < 0x80000000UL) {
|
||||||
|
*octets_needed = 4;
|
||||||
|
} else {
|
||||||
|
*octets_needed = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns octet count for an u64_t.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||||
|
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed)
|
||||||
|
{
|
||||||
|
/* check if high u32 is 0 */
|
||||||
|
if (*value == 0x00) {
|
||||||
|
/* only low u32 is important */
|
||||||
|
value++;
|
||||||
|
snmp_asn1_enc_u32t_cnt(*value, octets_needed);
|
||||||
|
} else {
|
||||||
|
/* low u32 does not matter for length determination */
|
||||||
|
snmp_asn1_enc_u32t_cnt(*value, octets_needed);
|
||||||
|
*octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns octet count for an s32_t.
|
||||||
|
*
|
||||||
|
* @param value value to be encoded
|
||||||
|
* @param octets_needed points to the return value
|
||||||
|
*
|
||||||
|
* @note ASN coded integers are _always_ signed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
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) {
|
||||||
|
*octets_needed = 2;
|
||||||
|
} else if (value < 0x800000L) {
|
||||||
|
*octets_needed = 3;
|
||||||
|
} else {
|
||||||
|
*octets_needed = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns octet count for an object identifier.
|
||||||
|
*
|
||||||
|
* @param oid points to object identifier array
|
||||||
|
* @param oid_len object identifier array length
|
||||||
|
* @param octets_needed points to the return value
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed)
|
||||||
|
{
|
||||||
|
u32_t sub_id;
|
||||||
|
|
||||||
|
*octets_needed = 0;
|
||||||
|
if (oid_len > 1) {
|
||||||
|
/* compressed prefix in one octet */
|
||||||
|
(*octets_needed)++;
|
||||||
|
oid_len -= 2;
|
||||||
|
oid += 2;
|
||||||
|
}
|
||||||
|
while (oid_len > 0) {
|
||||||
|
oid_len--;
|
||||||
|
sub_id = *oid;
|
||||||
|
|
||||||
|
sub_id >>= 7;
|
||||||
|
(*octets_needed)++;
|
||||||
|
while (sub_id > 0) {
|
||||||
|
sub_id >>= 7;
|
||||||
|
(*octets_needed)++;
|
||||||
|
}
|
||||||
|
oid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a TLV from a pbuf stream.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param tlv returns decoded TLV
|
||||||
|
* @return ERR_OK if successful, ERR_VAL if we can't decode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv)
|
||||||
|
{
|
||||||
|
u8_t data;
|
||||||
|
|
||||||
|
/* decode type first */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
tlv->type = data;
|
||||||
|
|
||||||
|
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) {
|
||||||
|
/* extended format is not used by SNMP so we do not accept those values */
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
tlv->type_len = 1;
|
||||||
|
|
||||||
|
/* now, decode length */
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
|
||||||
|
if (data < 0x80) { /* short form */
|
||||||
|
tlv->length_len = 1;
|
||||||
|
tlv->value_len = data;
|
||||||
|
} else if (data > 0x80) { /* long form */
|
||||||
|
u8_t length_bytes = data - 0x80;
|
||||||
|
tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */
|
||||||
|
tlv->value_len = 0;
|
||||||
|
|
||||||
|
while (length_bytes > 0) {
|
||||||
|
/* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */
|
||||||
|
if (tlv->value_len > 0xFF) {
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
length_bytes--;
|
||||||
|
}
|
||||||
|
} else { /* data == 0x80 indefinite length form */
|
||||||
|
/* (not allowed for SNMP; RFC 1157, 3.2.2) */
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes positive integer (counter, gauge, timeticks) into u32_t.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param len length of the coded integer field
|
||||||
|
* @param value return host order integer
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
|
||||||
|
*
|
||||||
|
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||||
|
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||||
|
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value)
|
||||||
|
{
|
||||||
|
u8_t data;
|
||||||
|
|
||||||
|
if ((len > 0) && (len <= 5)) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
|
||||||
|
/* expecting sign bit to be zero, only unsigned please! */
|
||||||
|
if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) {
|
||||||
|
*value = data;
|
||||||
|
len--;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
len--;
|
||||||
|
|
||||||
|
*value <<= 8;
|
||||||
|
*value |= data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes large positive integer (counter64) into 2x u32_t.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param len length of the coded integer field
|
||||||
|
* @param value return host order integer
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
|
||||||
|
*
|
||||||
|
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||||
|
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||||
|
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value)
|
||||||
|
{
|
||||||
|
u8_t data;
|
||||||
|
|
||||||
|
if (len <= 4) {
|
||||||
|
/* high u32 is 0 */
|
||||||
|
*value = 0;
|
||||||
|
/* directly skip to low u32 */
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len > 0) && (len <= 9)) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
|
||||||
|
/* expecting sign bit to be zero, only unsigned please! */
|
||||||
|
if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) {
|
||||||
|
*value = data;
|
||||||
|
len--;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
|
||||||
|
if (len == 4) {
|
||||||
|
/* skip to low u32 */
|
||||||
|
value++;
|
||||||
|
*value = 0;
|
||||||
|
} else {
|
||||||
|
*value <<= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value |= data;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes integer into s32_t.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param len length of the coded integer field
|
||||||
|
* @param value return host order integer
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
|
||||||
|
*
|
||||||
|
* @note ASN coded integers are _always_ signed!
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value)
|
||||||
|
{
|
||||||
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
u8_t *lsb_ptr = (u8_t*)value;
|
||||||
|
#endif
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1;
|
||||||
|
#endif
|
||||||
|
u8_t sign;
|
||||||
|
u8_t data;
|
||||||
|
|
||||||
|
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;
|
||||||
|
sign = 1;
|
||||||
|
*lsb_ptr &= data;
|
||||||
|
} else {
|
||||||
|
/* positive, start from 0 */
|
||||||
|
*value = 0;
|
||||||
|
sign = 0;
|
||||||
|
*lsb_ptr |= data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OR/AND octets with value */
|
||||||
|
while (len > 0) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
len--;
|
||||||
|
|
||||||
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
*value <<= 8;
|
||||||
|
#endif
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
*value >>= 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sign) {
|
||||||
|
*lsb_ptr |= 255;
|
||||||
|
*lsb_ptr &= data;
|
||||||
|
} else {
|
||||||
|
*lsb_ptr |= data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes object identifier from incoming message into array of u32_t.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param len length of the coded object identifier
|
||||||
|
* @param oid return decoded object identifier
|
||||||
|
* @param oid_len return decoded object identifier length
|
||||||
|
* @param oid_max_len size of oid buffer
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len)
|
||||||
|
{
|
||||||
|
u32_t *oid_ptr;
|
||||||
|
u8_t data;
|
||||||
|
|
||||||
|
*oid_len = 0;
|
||||||
|
oid_ptr = oid;
|
||||||
|
if (len > 0) {
|
||||||
|
if (oid_max_len < 2) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
len--;
|
||||||
|
|
||||||
|
/* first compressed octet */
|
||||||
|
if (data == 0x2B) {
|
||||||
|
/* (most) common case 1.3 (iso.org) */
|
||||||
|
*oid_ptr = 1;
|
||||||
|
oid_ptr++;
|
||||||
|
*oid_ptr = 3;
|
||||||
|
oid_ptr++;
|
||||||
|
} else if (data < 40) {
|
||||||
|
*oid_ptr = 0;
|
||||||
|
oid_ptr++;
|
||||||
|
*oid_ptr = data;
|
||||||
|
oid_ptr++;
|
||||||
|
} else if (data < 80) {
|
||||||
|
*oid_ptr = 1;
|
||||||
|
oid_ptr++;
|
||||||
|
*oid_ptr = data - 40;
|
||||||
|
oid_ptr++;
|
||||||
|
} else {
|
||||||
|
*oid_ptr = 2;
|
||||||
|
oid_ptr++;
|
||||||
|
*oid_ptr = data - 80;
|
||||||
|
oid_ptr++;
|
||||||
|
}
|
||||||
|
*oid_len = 2;
|
||||||
|
} else {
|
||||||
|
/* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((len > 0) && (*oid_len < oid_max_len)) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if ((data & 0x80) == 0x00) {
|
||||||
|
/* sub-identifier uses single octet */
|
||||||
|
*oid_ptr = data;
|
||||||
|
} else {
|
||||||
|
/* sub-identifier uses multiple octets */
|
||||||
|
u32_t sub_id = (data & ~0x80);
|
||||||
|
while ((len > 0) && ((data & 0x80) != 0)) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||||
|
len--;
|
||||||
|
|
||||||
|
sub_id = (sub_id << 7) + (data & ~0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((data & 0x80) != 0) {
|
||||||
|
/* "more bytes following" bit still set at end of len */
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
*oid_ptr = sub_id;
|
||||||
|
}
|
||||||
|
oid_ptr++;
|
||||||
|
(*oid_len)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
/* OID to long to fit in our buffer */
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding)
|
||||||
|
* from incoming message into array.
|
||||||
|
*
|
||||||
|
* @param pbuf_stream points to a pbuf stream
|
||||||
|
* @param len length of the coded raw data (zero is valid, e.g. empty string!)
|
||||||
|
* @param buf return raw bytes
|
||||||
|
* @param buf_len returns length of the raw return value
|
||||||
|
* @param buf_max_len buffer size
|
||||||
|
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len)
|
||||||
|
{
|
||||||
|
if (len > buf_max_len) {
|
||||||
|
/* not enough dst space */
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
*buf_len = len;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf));
|
||||||
|
buf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
108
ext/lwip/src/apps/snmp/snmp_asn1.h
Executable file
108
ext/lwip/src/apps/snmp/snmp_asn1.h
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Abstract Syntax Notation One (ISO 8824, 8825) codec.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* Copyright (c) 2016 Elias Oenal.
|
||||||
|
* 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: Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
* Martin Hentschel <info@cl-soft.de>
|
||||||
|
* Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIP_HDR_APPS_SNMP_ASN1_H
|
||||||
|
#define LWIP_HDR_APPS_SNMP_ASN1_H
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "snmp_pbuf_stream.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80
|
||||||
|
|
||||||
|
#define SNMP_ASN1_CLASS_MASK 0xC0
|
||||||
|
#define SNMP_ASN1_CONTENTTYPE_MASK 0x20
|
||||||
|
#define SNMP_ASN1_DATATYPE_MASK 0x1F
|
||||||
|
#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */
|
||||||
|
|
||||||
|
/* context specific (SNMP) tags (from SNMP spec. RFC1157) */
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_TRAP 4
|
||||||
|
#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5
|
||||||
|
|
||||||
|
#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0
|
||||||
|
#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2
|
||||||
|
|
||||||
|
struct snmp_asn1_tlv
|
||||||
|
{
|
||||||
|
u8_t type; /* only U8 because extended types are not specified by SNMP */
|
||||||
|
u8_t type_len; /* encoded length of 'type' field (normally 1) */
|
||||||
|
u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */
|
||||||
|
u16_t value_len; /* encoded length of the value */
|
||||||
|
};
|
||||||
|
#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len)
|
||||||
|
#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len)
|
||||||
|
#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0);
|
||||||
|
|
||||||
|
err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv);
|
||||||
|
err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value);
|
||||||
|
err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value);
|
||||||
|
err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value);
|
||||||
|
err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len);
|
||||||
|
err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len);
|
||||||
|
|
||||||
|
err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv);
|
||||||
|
|
||||||
|
void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed);
|
||||||
|
void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed);
|
||||||
|
void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed);
|
||||||
|
void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed);
|
||||||
|
void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed);
|
||||||
|
err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len);
|
||||||
|
err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value);
|
||||||
|
err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value);
|
||||||
|
err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value);
|
||||||
|
err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */
|
||||||
1349
ext/lwip/src/apps/snmp/snmp_core.c
Executable file
1349
ext/lwip/src/apps/snmp/snmp_core.c
Executable file
File diff suppressed because it is too large
Load Diff
76
ext/lwip/src/apps/snmp/snmp_core_priv.h
Executable file
76
ext/lwip/src/apps/snmp/snmp_core_priv.h
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel <info@cl-soft.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H
|
||||||
|
#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "snmp_asn1.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* (outdated) SNMPv1 error codes
|
||||||
|
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request
|
||||||
|
*/
|
||||||
|
#define SNMP_ERR_NOSUCHNAME 2
|
||||||
|
#define SNMP_ERR_BADVALUE 3
|
||||||
|
#define SNMP_ERR_READONLY 4
|
||||||
|
/* error codes which are internal and shall not be used by MIBS
|
||||||
|
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request
|
||||||
|
*/
|
||||||
|
#define SNMP_ERR_TOOBIG 1
|
||||||
|
#define SNMP_ERR_AUTHORIZATIONERROR 16
|
||||||
|
#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT
|
||||||
|
#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW
|
||||||
|
|
||||||
|
|
||||||
|
const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len);
|
||||||
|
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);
|
||||||
|
|
||||||
|
typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*);
|
||||||
|
|
||||||
|
u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */
|
||||||
116
ext/lwip/src/apps/snmp/snmp_mib2.c
Executable file
116
ext/lwip/src/apps/snmp/snmp_mib2.c
Executable file
@@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup snmp_mib2 MIB2
|
||||||
|
* @ingroup snmp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#if !LWIP_STATS
|
||||||
|
#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2)
|
||||||
|
#endif
|
||||||
|
#if !MIB2_STATS
|
||||||
|
#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#include "lwip/tcpip.h"
|
||||||
|
#include "lwip/priv/tcpip_priv.h"
|
||||||
|
void
|
||||||
|
snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg)
|
||||||
|
{
|
||||||
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
|
LOCK_TCPIP_CORE();
|
||||||
|
fn(arg);
|
||||||
|
UNLOCK_TCPIP_CORE();
|
||||||
|
#else
|
||||||
|
tcpip_callback(fn, arg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct snmp_threadsync_instance snmp_mib2_lwip_locks;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */
|
||||||
|
/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */
|
||||||
|
/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */
|
||||||
|
|
||||||
|
/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */
|
||||||
|
extern const struct snmp_scalar_array_node snmp_mib2_snmp_root;
|
||||||
|
extern const struct snmp_tree_node snmp_mib2_udp_root;
|
||||||
|
extern const struct snmp_tree_node snmp_mib2_tcp_root;
|
||||||
|
extern const struct snmp_scalar_array_node snmp_mib2_icmp_root;
|
||||||
|
extern const struct snmp_tree_node snmp_mib2_interface_root;
|
||||||
|
extern const struct snmp_scalar_array_node snmp_mib2_system_node;
|
||||||
|
extern const struct snmp_tree_node snmp_mib2_at_root;
|
||||||
|
extern const struct snmp_tree_node snmp_mib2_ip_root;
|
||||||
|
|
||||||
|
static const struct snmp_node* const mib2_nodes[] = {
|
||||||
|
&snmp_mib2_system_node.node.node,
|
||||||
|
&snmp_mib2_interface_root.node,
|
||||||
|
#if LWIP_ARP && LWIP_IPV4
|
||||||
|
&snmp_mib2_at_root.node,
|
||||||
|
#endif /* LWIP_ARP && LWIP_IPV4 */
|
||||||
|
#if LWIP_IPV4
|
||||||
|
&snmp_mib2_ip_root.node,
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
#if LWIP_ICMP
|
||||||
|
&snmp_mib2_icmp_root.node.node,
|
||||||
|
#endif /* LWIP_ICMP */
|
||||||
|
#if LWIP_TCP
|
||||||
|
&snmp_mib2_tcp_root.node,
|
||||||
|
#endif /* LWIP_TCP */
|
||||||
|
#if LWIP_UDP
|
||||||
|
&snmp_mib2_udp_root.node,
|
||||||
|
#endif /* LWIP_UDP */
|
||||||
|
&snmp_mib2_snmp_root.node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes);
|
||||||
|
|
||||||
|
static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 };
|
||||||
|
const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node);
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
||||||
182
ext/lwip/src/apps/snmp/snmp_mib2_icmp.c
Executable file
182
ext/lwip/src/apps/snmp/snmp_mib2_icmp.c
Executable file
@@ -0,0 +1,182 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) ICMP objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/icmp.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
|
||||||
|
{
|
||||||
|
u32_t *uint_ptr = (u32_t*)value;
|
||||||
|
|
||||||
|
switch (node->oid) {
|
||||||
|
case 1: /* icmpInMsgs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinmsgs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 2: /* icmpInErrors */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinerrors);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 3: /* icmpInDestUnreachs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpindestunreachs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 4: /* icmpInTimeExcds */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpintimeexcds);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 5: /* icmpInParmProbs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinparmprobs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 6: /* icmpInSrcQuenchs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinsrcquenchs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 7: /* icmpInRedirects */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinredirects);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 8: /* icmpInEchos */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinechos);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 9: /* icmpInEchoReps */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinechoreps);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 10: /* icmpInTimestamps */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpintimestamps);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 11: /* icmpInTimestampReps */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpintimestampreps);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 12: /* icmpInAddrMasks */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinaddrmasks);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 13: /* icmpInAddrMaskReps */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 14: /* icmpOutMsgs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpoutmsgs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 15: /* icmpOutErrors */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpouterrors);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 16: /* icmpOutDestUnreachs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpoutdestunreachs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 17: /* icmpOutTimeExcds */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpouttimeexcds);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 18: /* icmpOutParmProbs: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 20: /* icmpOutRedirects: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 21: /* icmpOutEchos */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpoutechos);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 22: /* icmpOutEchoReps */
|
||||||
|
*uint_ptr = STATS_GET(mib2.icmpoutechoreps);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 23: /* icmpOutTimestamps: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 24: /* icmpOutTimestampReps: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 25: /* icmpOutAddrMasks: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct snmp_scalar_array_node_def icmp_nodes[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
|
||||||
|
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL);
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */
|
||||||
375
ext/lwip/src/apps/snmp/snmp_mib2_interfaces.c
Executable file
375
ext/lwip/src/apps/snmp/snmp_mib2_interfaces.c
Executable file
@@ -0,0 +1,375 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) INTERFACES objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
interfaces_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
if (instance->node->oid == 1) {
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
s32_t num_netifs = 0;
|
||||||
|
|
||||||
|
struct netif *netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
num_netifs++;
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sint_ptr = num_netifs;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range interfaces_Table_oid_ranges[] = {
|
||||||
|
{ 1, 0xff } /* netif->num is u8_t */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8_t iftable_ifOutQLen = 0;
|
||||||
|
|
||||||
|
static const u8_t iftable_ifOperStatus_up = 1;
|
||||||
|
static const u8_t iftable_ifOperStatus_down = 2;
|
||||||
|
|
||||||
|
static const u8_t iftable_ifAdminStatus_up = 1;
|
||||||
|
static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7;
|
||||||
|
static const u8_t iftable_ifAdminStatus_down = 2;
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance)
|
||||||
|
{
|
||||||
|
u32_t ifIndex;
|
||||||
|
struct netif *netif;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(column);
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get netif index from incoming OID */
|
||||||
|
ifIndex = row_oid[0];
|
||||||
|
|
||||||
|
/* find netif with index */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
if (netif_to_num(netif) == ifIndex) {
|
||||||
|
/* store netif pointer for subsequent operations (get/test/set) */
|
||||||
|
cell_instance->reference.ptr = netif;
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance)
|
||||||
|
{
|
||||||
|
struct netif *netif;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
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));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
|
||||||
|
test_oid[0] = netif_to_num(netif);
|
||||||
|
|
||||||
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
|
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif);
|
||||||
|
|
||||||
|
netif = netif->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);
|
||||||
|
/* store netif pointer for subsequent operations (get/test/set) */
|
||||||
|
cell_instance->reference.ptr = /* (struct netif*) */state.reference;
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
interfaces_Table_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
struct netif *netif = (struct netif*)instance->reference.ptr;
|
||||||
|
u32_t* value_u32 = (u32_t*)value;
|
||||||
|
s32_t* value_s32 = (s32_t*)value;
|
||||||
|
u16_t value_len;
|
||||||
|
|
||||||
|
switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
|
||||||
|
{
|
||||||
|
case 1: /* ifIndex */
|
||||||
|
*value_s32 = netif_to_num(netif);
|
||||||
|
value_len = sizeof(*value_s32);
|
||||||
|
break;
|
||||||
|
case 2: /* ifDescr */
|
||||||
|
value_len = sizeof(netif->name);
|
||||||
|
MEMCPY(value, netif->name, value_len);
|
||||||
|
break;
|
||||||
|
case 3: /* ifType */
|
||||||
|
*value_s32 = netif->link_type;
|
||||||
|
value_len = sizeof(*value_s32);
|
||||||
|
break;
|
||||||
|
case 4: /* ifMtu */
|
||||||
|
*value_s32 = netif->mtu;
|
||||||
|
value_len = sizeof(*value_s32);
|
||||||
|
break;
|
||||||
|
case 5: /* ifSpeed */
|
||||||
|
*value_u32 = netif->link_speed;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 6: /* ifPhysAddress */
|
||||||
|
value_len = sizeof(netif->hwaddr);
|
||||||
|
MEMCPY(value, &netif->hwaddr, value_len);
|
||||||
|
break;
|
||||||
|
case 7: /* ifAdminStatus */
|
||||||
|
if (netif_is_up(netif)) {
|
||||||
|
*value_s32 = iftable_ifOperStatus_up;
|
||||||
|
} else {
|
||||||
|
*value_s32 = iftable_ifOperStatus_down;
|
||||||
|
}
|
||||||
|
value_len = sizeof(*value_s32);
|
||||||
|
break;
|
||||||
|
case 8: /* ifOperStatus */
|
||||||
|
if (netif_is_up(netif)) {
|
||||||
|
if (netif_is_link_up(netif)) {
|
||||||
|
*value_s32 = iftable_ifAdminStatus_up;
|
||||||
|
} else {
|
||||||
|
*value_s32 = iftable_ifAdminStatus_lowerLayerDown;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*value_s32 = iftable_ifAdminStatus_down;
|
||||||
|
}
|
||||||
|
value_len = sizeof(*value_s32);
|
||||||
|
break;
|
||||||
|
case 9: /* ifLastChange */
|
||||||
|
*value_u32 = netif->ts;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 10: /* ifInOctets */
|
||||||
|
*value_u32 = netif->mib2_counters.ifinoctets;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 11: /* ifInUcastPkts */
|
||||||
|
*value_u32 = netif->mib2_counters.ifinucastpkts;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 12: /* ifInNUcastPkts */
|
||||||
|
*value_u32 = netif->mib2_counters.ifinnucastpkts;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 13: /* ifInDiscards */
|
||||||
|
*value_u32 = netif->mib2_counters.ifindiscards;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 14: /* ifInErrors */
|
||||||
|
*value_u32 = netif->mib2_counters.ifinerrors;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 15: /* ifInUnkownProtos */
|
||||||
|
*value_u32 = netif->mib2_counters.ifinunknownprotos;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 16: /* ifOutOctets */
|
||||||
|
*value_u32 = netif->mib2_counters.ifoutoctets;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 17: /* ifOutUcastPkts */
|
||||||
|
*value_u32 = netif->mib2_counters.ifoutucastpkts;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 18: /* ifOutNUcastPkts */
|
||||||
|
*value_u32 = netif->mib2_counters.ifoutnucastpkts;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 19: /* ifOutDiscarts */
|
||||||
|
*value_u32 = netif->mib2_counters.ifoutdiscards;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 20: /* ifOutErrors */
|
||||||
|
*value_u32 = netif->mib2_counters.ifouterrors;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
case 21: /* ifOutQLen */
|
||||||
|
*value_u32 = iftable_ifOutQLen;
|
||||||
|
value_len = sizeof(*value_u32);
|
||||||
|
break;
|
||||||
|
/** @note returning zeroDotZero (0.0) no media specific MIB support */
|
||||||
|
case 22: /* ifSpecific */
|
||||||
|
value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
|
||||||
|
MEMCPY(value, snmp_zero_dot_zero.id, value_len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !SNMP_SAFE_REQUESTS
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
|
||||||
|
/* stack should never call this method for another column,
|
||||||
|
because all other columns are set to readonly */
|
||||||
|
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) {
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_WRONGVALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
struct netif *netif = (struct netif*)instance->reference.ptr;
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
|
||||||
|
/* stack should never call this method for another column,
|
||||||
|
because all other columns are set to readonly */
|
||||||
|
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
|
||||||
|
if (*sint_ptr == 1) {
|
||||||
|
netif_set_up(netif);
|
||||||
|
} else if (*sint_ptr == 2) {
|
||||||
|
netif_set_down(netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SNMP_SAFE_REQUESTS */
|
||||||
|
|
||||||
|
static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value);
|
||||||
|
|
||||||
|
static const struct snmp_table_col_def interfaces_Table_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */
|
||||||
|
{ 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */
|
||||||
|
{ 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */
|
||||||
|
#if !SNMP_SAFE_REQUESTS
|
||||||
|
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */
|
||||||
|
#else
|
||||||
|
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */
|
||||||
|
#endif
|
||||||
|
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */
|
||||||
|
{ 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */
|
||||||
|
{ 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */
|
||||||
|
{ 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */
|
||||||
|
{ 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */
|
||||||
|
{ 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */
|
||||||
|
{ 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */
|
||||||
|
{ 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */
|
||||||
|
{ 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */
|
||||||
|
{ 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */
|
||||||
|
{ 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */
|
||||||
|
{ 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */
|
||||||
|
{ 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */
|
||||||
|
{ 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */
|
||||||
|
{ 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */
|
||||||
|
};
|
||||||
|
|
||||||
|
#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,
|
||||||
|
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,
|
||||||
|
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 */
|
||||||
|
CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
|
||||||
|
CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
|
||||||
|
|
||||||
|
static const struct snmp_node* const interface_nodes[] = {
|
||||||
|
&SYNC_NODE_NAME(interfaces_Number).node.node,
|
||||||
|
&SYNC_NODE_NAME(interfaces_Table).node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes);
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
||||||
743
ext/lwip/src/apps/snmp/snmp_mib2_ip.c
Executable file
743
ext/lwip/src/apps/snmp/snmp_mib2_ip.c
Executable file
@@ -0,0 +1,743 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) IP objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/etharp.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
ip_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
s32_t* sint_ptr = (s32_t*)value;
|
||||||
|
u32_t* uint_ptr = (u32_t*)value;
|
||||||
|
|
||||||
|
switch (instance->node->oid) {
|
||||||
|
case 1: /* ipForwarding */
|
||||||
|
#if IP_FORWARD
|
||||||
|
/* forwarding */
|
||||||
|
*sint_ptr = 1;
|
||||||
|
#else
|
||||||
|
/* not-forwarding */
|
||||||
|
*sint_ptr = 2;
|
||||||
|
#endif
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 2: /* ipDefaultTTL */
|
||||||
|
*sint_ptr = IP_DEFAULT_TTL;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 3: /* ipInReceives */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipinreceives);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 4: /* ipInHdrErrors */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipinhdrerrors);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 5: /* ipInAddrErrors */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipinaddrerrors);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 6: /* ipForwDatagrams */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipforwdatagrams);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 7: /* ipInUnknownProtos */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipinunknownprotos);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 8: /* ipInDiscards */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipindiscards);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 9: /* ipInDelivers */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipindelivers);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 10: /* ipOutRequests */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipoutrequests);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 11: /* ipOutDiscards */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipoutdiscards);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 12: /* ipOutNoRoutes */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipoutnoroutes);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 13: /* ipReasmTimeout */
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
*sint_ptr = IP_REASS_MAXAGE;
|
||||||
|
#else
|
||||||
|
*sint_ptr = 0;
|
||||||
|
#endif
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 14: /* ipReasmReqds */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipreasmreqds);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 15: /* ipReasmOKs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipreasmoks);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 16: /* ipReasmFails */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipreasmfails);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 17: /* ipFragOKs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipfragoks);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 18: /* ipFragFails */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipfragfails);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 19: /* ipFragCreates */
|
||||||
|
*uint_ptr = STATS_GET(mib2.ipfragcreates);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 23: /* ipRoutingDiscards: not supported -> always 0 */
|
||||||
|
*uint_ptr = 0;
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test ip object value before setting.
|
||||||
|
*
|
||||||
|
* @param instance node instance
|
||||||
|
* @param len return value space (in bytes)
|
||||||
|
* @param value points to (varbind) space to copy value from.
|
||||||
|
*
|
||||||
|
* @note we allow set if the value matches the hardwired value,
|
||||||
|
* otherwise return badvalue.
|
||||||
|
*/
|
||||||
|
static snmp_err_t
|
||||||
|
ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
switch (instance->node->oid) {
|
||||||
|
case 1: /* ipForwarding */
|
||||||
|
#if IP_FORWARD
|
||||||
|
/* forwarding */
|
||||||
|
if (*sint_ptr == 1)
|
||||||
|
#else
|
||||||
|
/* not-forwarding */
|
||||||
|
if (*sint_ptr == 2)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* ipDefaultTTL */
|
||||||
|
if (*sint_ptr == IP_DEFAULT_TTL) {
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(instance);
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
LWIP_UNUSED_ARG(value);
|
||||||
|
/* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- ipAddrTable --- */
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = {
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff } /* IP D */
|
||||||
|
};
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
switch (*column) {
|
||||||
|
case 1: /* ipAdEntAddr */
|
||||||
|
value->u32 = netif_ip4_addr(netif)->addr;
|
||||||
|
break;
|
||||||
|
case 2: /* ipAdEntIfIndex */
|
||||||
|
value->u32 = netif_to_num(netif);
|
||||||
|
break;
|
||||||
|
case 3: /* ipAdEntNetMask */
|
||||||
|
value->u32 = netif_ip4_netmask(netif)->addr;
|
||||||
|
break;
|
||||||
|
case 4: /* ipAdEntBcastAddr */
|
||||||
|
/* lwIP oddity, there's no broadcast
|
||||||
|
address in the netif we can rely on */
|
||||||
|
value->u32 = IPADDR_BROADCAST & 1;
|
||||||
|
break;
|
||||||
|
case 5: /* ipAdEntReasmMaxSize */
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
/* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
|
||||||
|
* but only if receiving one fragmented packet at a time.
|
||||||
|
* The current solution is to calculate for 2 simultaneous packets...
|
||||||
|
*/
|
||||||
|
value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) *
|
||||||
|
(PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN)));
|
||||||
|
#else
|
||||||
|
/** @todo returning MTU would be a bad thing and
|
||||||
|
returning a wild guess like '576' isn't good either */
|
||||||
|
value->u32 = 0;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_AddrTable_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)
|
||||||
|
{
|
||||||
|
ip4_addr_t ip;
|
||||||
|
struct netif *netif;
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get IP from incoming OID */
|
||||||
|
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
|
||||||
|
|
||||||
|
/* find netif with requested ip */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_AddrTable_get_cell_value_core(netif, column, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct netif *netif;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
|
||||||
|
snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]);
|
||||||
|
|
||||||
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
|
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif);
|
||||||
|
|
||||||
|
netif = netif->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);
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- ipRouteTable --- */
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = {
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff }, /* IP D */
|
||||||
|
};
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
switch (*column) {
|
||||||
|
case 1: /* ipRouteDest */
|
||||||
|
if (default_route) {
|
||||||
|
/* default rte has 0.0.0.0 dest */
|
||||||
|
value->u32 = IP4_ADDR_ANY4->addr;
|
||||||
|
} else {
|
||||||
|
/* netifs have netaddress dest */
|
||||||
|
ip4_addr_t tmp;
|
||||||
|
ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif));
|
||||||
|
value->u32 = tmp.addr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* ipRouteIfIndex */
|
||||||
|
value->u32 = netif_to_num(netif);
|
||||||
|
break;
|
||||||
|
case 3: /* ipRouteMetric1 */
|
||||||
|
if (default_route) {
|
||||||
|
value->s32 = 1; /* default */
|
||||||
|
} else {
|
||||||
|
value->s32 = 0; /* normal */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: /* ipRouteMetric2 */
|
||||||
|
case 5: /* ipRouteMetric3 */
|
||||||
|
case 6: /* ipRouteMetric4 */
|
||||||
|
value->s32 = -1; /* none */
|
||||||
|
break;
|
||||||
|
case 7: /* ipRouteNextHop */
|
||||||
|
if (default_route) {
|
||||||
|
/* default rte: gateway */
|
||||||
|
value->u32 = netif_ip4_gw(netif)->addr;
|
||||||
|
} else {
|
||||||
|
/* other rtes: netif ip_addr */
|
||||||
|
value->u32 = netif_ip4_addr(netif)->addr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8: /* ipRouteType */
|
||||||
|
if (default_route) {
|
||||||
|
/* default rte is indirect */
|
||||||
|
value->u32 = 4; /* indirect */
|
||||||
|
} else {
|
||||||
|
/* other rtes are direct */
|
||||||
|
value->u32 = 3; /* direct */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9: /* ipRouteProto */
|
||||||
|
/* locally defined routes */
|
||||||
|
value->u32 = 2; /* local */
|
||||||
|
break;
|
||||||
|
case 10: /* ipRouteAge */
|
||||||
|
/* @todo (sysuptime - timestamp last change) / 100 */
|
||||||
|
value->u32 = 0;
|
||||||
|
break;
|
||||||
|
case 11: /* ipRouteMask */
|
||||||
|
if (default_route) {
|
||||||
|
/* default rte use 0.0.0.0 mask */
|
||||||
|
value->u32 = IP4_ADDR_ANY4->addr;
|
||||||
|
} else {
|
||||||
|
/* other rtes use netmask */
|
||||||
|
value->u32 = netif_ip4_netmask(netif)->addr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12: /* ipRouteMetric5 */
|
||||||
|
value->s32 = -1; /* none */
|
||||||
|
break;
|
||||||
|
case 13: /* ipRouteInfo */
|
||||||
|
value->const_ptr = snmp_zero_dot_zero.id;
|
||||||
|
*value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_RouteTable_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)
|
||||||
|
{
|
||||||
|
ip4_addr_t test_ip;
|
||||||
|
struct netif *netif;
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get IP and port from incoming OID */
|
||||||
|
snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */
|
||||||
|
|
||||||
|
/* default route is on default netif */
|
||||||
|
if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find netif with requested route */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
ip4_addr_t dst;
|
||||||
|
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
|
||||||
|
|
||||||
|
if (ip4_addr_cmp(&dst, &test_ip)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct netif *netif;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges));
|
||||||
|
|
||||||
|
/* check default route */
|
||||||
|
if (netif_default != NULL) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
ip4_addr_t dst;
|
||||||
|
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
|
||||||
|
|
||||||
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
|
if (!ip4_addr_isany_val(dst)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* did we find a next one? */
|
||||||
|
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
||||||
|
ip4_addr_t dst;
|
||||||
|
snmp_oid_to_ip4(&result_temp[0], &dst);
|
||||||
|
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len);
|
||||||
|
} else {
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_ARP && LWIP_IPV4
|
||||||
|
/* --- ipNetToMediaTable --- */
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = {
|
||||||
|
{ 1, 0xff }, /* IfIndex */
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff } /* IP D */
|
||||||
|
};
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
ip4_addr_t *ip;
|
||||||
|
struct netif *netif;
|
||||||
|
struct eth_addr *ethaddr;
|
||||||
|
|
||||||
|
etharp_get_entry(arp_table_index, &ip, &netif, ðaddr);
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
switch (*column) {
|
||||||
|
case 1: /* atIfIndex / ipNetToMediaIfIndex */
|
||||||
|
value->u32 = netif_to_num(netif);
|
||||||
|
break;
|
||||||
|
case 2: /* atPhysAddress / ipNetToMediaPhysAddress */
|
||||||
|
value->ptr = ethaddr;
|
||||||
|
*value_len = sizeof(*ethaddr);
|
||||||
|
break;
|
||||||
|
case 3: /* atNetAddress / ipNetToMediaNetAddress */
|
||||||
|
value->u32 = ip->addr;
|
||||||
|
break;
|
||||||
|
case 4: /* ipNetToMediaType */
|
||||||
|
value->u32 = 3; /* dynamic*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_NetToMediaTable_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)
|
||||||
|
{
|
||||||
|
ip4_addr_t ip_in;
|
||||||
|
u8_t netif_index;
|
||||||
|
u8_t i;
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get IP from incoming OID */
|
||||||
|
netif_index = (u8_t)row_oid[0];
|
||||||
|
snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */
|
||||||
|
|
||||||
|
/* find requested entry */
|
||||||
|
for (i=0; i<ARP_TABLE_SIZE; i++) {
|
||||||
|
ip4_addr_t *ip;
|
||||||
|
struct netif *netif;
|
||||||
|
struct eth_addr *ethaddr;
|
||||||
|
|
||||||
|
if (etharp_get_entry(i, &ip, &netif, ðaddr)) {
|
||||||
|
if ((netif_index == netif_to_num(netif)) && ip4_addr_cmp(&ip_in, ip)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_NetToMediaTable_get_cell_value_core(i, column, value, value_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
u8_t i;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
for (i=0; i<ARP_TABLE_SIZE; i++) {
|
||||||
|
ip4_addr_t *ip;
|
||||||
|
struct netif *netif;
|
||||||
|
struct eth_addr *ethaddr;
|
||||||
|
|
||||||
|
if (etharp_get_entry(i, &ip, &netif, ðaddr)) {
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
|
||||||
|
|
||||||
|
test_oid[0] = netif_to_num(netif);
|
||||||
|
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), LWIP_PTR_NUMERIC_CAST(void*, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return ip_NetToMediaTable_get_cell_value_core(LWIP_PTR_NUMERIC_CAST(u8_t, state.reference), column, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_ARP && LWIP_IPV4 */
|
||||||
|
|
||||||
|
static const struct snmp_scalar_node ip_Forwarding = SNMP_SCALAR_CREATE_NODE(1, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
|
||||||
|
static const struct snmp_scalar_node ip_DefaultTTL = SNMP_SCALAR_CREATE_NODE(2, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
|
||||||
|
static const struct snmp_scalar_node ip_InReceives = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_InHdrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_InAddrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_ForwDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_InUnknownProtos = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_InDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_InDelivers = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_OutRequests = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_OutDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_OutNoRoutes = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_ReasmTimeout = SNMP_SCALAR_CREATE_NODE_READONLY(13, SNMP_ASN1_TYPE_INTEGER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_ReasmReqds = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_ReasmOKs = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_ReasmFails = SNMP_SCALAR_CREATE_NODE_READONLY(16, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_FragOKs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_FragFails = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_FragCreates = SNMP_SCALAR_CREATE_NODE_READONLY(19, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
static const struct snmp_scalar_node ip_RoutingDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(23, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_col_def ip_AddrTable_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntAddr */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntIfIndex */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntNetMask */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntBcastAddr */
|
||||||
|
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipAdEntReasmMaxSize */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node ip_AddrTable = SNMP_TABLE_CREATE_SIMPLE(20, ip_AddrTable_columns, ip_AddrTable_get_cell_value, ip_AddrTable_get_next_cell_instance_and_value);
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_col_def ip_RouteTable_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteDest */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteIfIndex */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric1 */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric2 */
|
||||||
|
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric3 */
|
||||||
|
{ 6, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric4 */
|
||||||
|
{ 7, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteNextHop */
|
||||||
|
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteType */
|
||||||
|
{ 9, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteProto */
|
||||||
|
{ 10, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteAge */
|
||||||
|
{ 11, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteMask */
|
||||||
|
{ 12, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric5 */
|
||||||
|
{ 13, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_VARIANT_VALUE_TYPE_PTR } /* ipRouteInfo */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node ip_RouteTable = SNMP_TABLE_CREATE_SIMPLE(21, ip_RouteTable_columns, ip_RouteTable_get_cell_value, ip_RouteTable_get_next_cell_instance_and_value);
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
#if LWIP_ARP && LWIP_IPV4
|
||||||
|
static const struct snmp_table_simple_col_def ip_NetToMediaTable_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaIfIndex */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* ipNetToMediaPhysAddress */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaNetAddress */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipNetToMediaType */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREATE_SIMPLE(22, ip_NetToMediaTable_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
|
||||||
|
#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 */
|
||||||
|
CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 3, ip_InReceives)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 4, ip_InHdrErrors)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 5, ip_InAddrErrors)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 6, ip_ForwDatagrams)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 7, ip_InUnknownProtos)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 8, ip_InDiscards)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 9, ip_InDelivers)
|
||||||
|
CREATE_LWIP_SYNC_NODE(10, ip_OutRequests)
|
||||||
|
CREATE_LWIP_SYNC_NODE(11, ip_OutDiscards)
|
||||||
|
CREATE_LWIP_SYNC_NODE(12, ip_OutNoRoutes)
|
||||||
|
CREATE_LWIP_SYNC_NODE(13, ip_ReasmTimeout)
|
||||||
|
CREATE_LWIP_SYNC_NODE(14, ip_ReasmReqds)
|
||||||
|
CREATE_LWIP_SYNC_NODE(15, ip_ReasmOKs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(15, ip_ReasmFails)
|
||||||
|
CREATE_LWIP_SYNC_NODE(17, ip_FragOKs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(18, ip_FragFails)
|
||||||
|
CREATE_LWIP_SYNC_NODE(19, ip_FragCreates)
|
||||||
|
CREATE_LWIP_SYNC_NODE(20, ip_AddrTable)
|
||||||
|
CREATE_LWIP_SYNC_NODE(21, ip_RouteTable)
|
||||||
|
#if LWIP_ARP
|
||||||
|
CREATE_LWIP_SYNC_NODE(22, ip_NetToMediaTable)
|
||||||
|
#endif /* LWIP_ARP */
|
||||||
|
CREATE_LWIP_SYNC_NODE(23, ip_RoutingDiscards)
|
||||||
|
|
||||||
|
static const struct snmp_node* const ip_nodes[] = {
|
||||||
|
&SYNC_NODE_NAME(ip_Forwarding).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_DefaultTTL).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InReceives).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InHdrErrors).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InAddrErrors).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_ForwDatagrams).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InUnknownProtos).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InDiscards).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_InDelivers).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_OutRequests).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_OutDiscards).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_OutNoRoutes).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_ReasmTimeout).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_ReasmReqds).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_ReasmOKs).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_ReasmFails).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_FragOKs).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_FragFails).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_FragCreates).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_AddrTable).node.node,
|
||||||
|
&SYNC_NODE_NAME(ip_RouteTable).node.node,
|
||||||
|
#if LWIP_ARP
|
||||||
|
&SYNC_NODE_NAME(ip_NetToMediaTable).node.node,
|
||||||
|
#endif /* LWIP_ARP */
|
||||||
|
&SYNC_NODE_NAME(ip_RoutingDiscards).node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_tree_node snmp_mib2_ip_root = SNMP_CREATE_TREE_NODE(4, ip_nodes);
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
/* --- at .1.3.6.1.2.1.3 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LWIP_ARP && LWIP_IPV4
|
||||||
|
/* at node table is a subset of ip_nettomedia table (same rows but less columns) */
|
||||||
|
static const struct snmp_table_simple_col_def at_Table_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* atIfIndex */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* atPhysAddress */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 } /* atNetAddress */
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
||||||
|
CREATE_LWIP_SYNC_NODE(1, at_Table)
|
||||||
|
|
||||||
|
static const struct snmp_node* const at_nodes[] = {
|
||||||
|
&SYNC_NODE_NAME(at_Table).node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_tree_node snmp_mib2_at_root = SNMP_CREATE_TREE_NODE(3, at_nodes);
|
||||||
|
#endif /* LWIP_ARP && LWIP_IPV4 */
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
||||||
227
ext/lwip/src/apps/snmp/snmp_mib2_snmp.c
Executable file
227
ext/lwip/src/apps/snmp/snmp_mib2_snmp.c
Executable file
@@ -0,0 +1,227 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) SNMP objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2
|
||||||
|
|
||||||
|
#define MIB2_AUTH_TRAPS_ENABLED 1
|
||||||
|
#define MIB2_AUTH_TRAPS_DISABLED 2
|
||||||
|
|
||||||
|
/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */
|
||||||
|
static s16_t
|
||||||
|
snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
|
||||||
|
{
|
||||||
|
u32_t *uint_ptr = (u32_t*)value;
|
||||||
|
switch (node->oid) {
|
||||||
|
case 1: /* snmpInPkts */
|
||||||
|
*uint_ptr = snmp_stats.inpkts;
|
||||||
|
break;
|
||||||
|
case 2: /* snmpOutPkts */
|
||||||
|
*uint_ptr = snmp_stats.outpkts;
|
||||||
|
break;
|
||||||
|
case 3: /* snmpInBadVersions */
|
||||||
|
*uint_ptr = snmp_stats.inbadversions;
|
||||||
|
break;
|
||||||
|
case 4: /* snmpInBadCommunityNames */
|
||||||
|
*uint_ptr = snmp_stats.inbadcommunitynames;
|
||||||
|
break;
|
||||||
|
case 5: /* snmpInBadCommunityUses */
|
||||||
|
*uint_ptr = snmp_stats.inbadcommunityuses;
|
||||||
|
break;
|
||||||
|
case 6: /* snmpInASNParseErrs */
|
||||||
|
*uint_ptr = snmp_stats.inasnparseerrs;
|
||||||
|
break;
|
||||||
|
case 8: /* snmpInTooBigs */
|
||||||
|
*uint_ptr = snmp_stats.intoobigs;
|
||||||
|
break;
|
||||||
|
case 9: /* snmpInNoSuchNames */
|
||||||
|
*uint_ptr = snmp_stats.innosuchnames;
|
||||||
|
break;
|
||||||
|
case 10: /* snmpInBadValues */
|
||||||
|
*uint_ptr = snmp_stats.inbadvalues;
|
||||||
|
break;
|
||||||
|
case 11: /* snmpInReadOnlys */
|
||||||
|
*uint_ptr = snmp_stats.inreadonlys;
|
||||||
|
break;
|
||||||
|
case 12: /* snmpInGenErrs */
|
||||||
|
*uint_ptr = snmp_stats.ingenerrs;
|
||||||
|
break;
|
||||||
|
case 13: /* snmpInTotalReqVars */
|
||||||
|
*uint_ptr = snmp_stats.intotalreqvars;
|
||||||
|
break;
|
||||||
|
case 14: /* snmpInTotalSetVars */
|
||||||
|
*uint_ptr = snmp_stats.intotalsetvars;
|
||||||
|
break;
|
||||||
|
case 15: /* snmpInGetRequests */
|
||||||
|
*uint_ptr = snmp_stats.ingetrequests;
|
||||||
|
break;
|
||||||
|
case 16: /* snmpInGetNexts */
|
||||||
|
*uint_ptr = snmp_stats.ingetnexts;
|
||||||
|
break;
|
||||||
|
case 17: /* snmpInSetRequests */
|
||||||
|
*uint_ptr = snmp_stats.insetrequests;
|
||||||
|
break;
|
||||||
|
case 18: /* snmpInGetResponses */
|
||||||
|
*uint_ptr = snmp_stats.ingetresponses;
|
||||||
|
break;
|
||||||
|
case 19: /* snmpInTraps */
|
||||||
|
*uint_ptr = snmp_stats.intraps;
|
||||||
|
break;
|
||||||
|
case 20: /* snmpOutTooBigs */
|
||||||
|
*uint_ptr = snmp_stats.outtoobigs;
|
||||||
|
break;
|
||||||
|
case 21: /* snmpOutNoSuchNames */
|
||||||
|
*uint_ptr = snmp_stats.outnosuchnames;
|
||||||
|
break;
|
||||||
|
case 22: /* snmpOutBadValues */
|
||||||
|
*uint_ptr = snmp_stats.outbadvalues;
|
||||||
|
break;
|
||||||
|
case 24: /* snmpOutGenErrs */
|
||||||
|
*uint_ptr = snmp_stats.outgenerrs;
|
||||||
|
break;
|
||||||
|
case 25: /* snmpOutGetRequests */
|
||||||
|
*uint_ptr = snmp_stats.outgetrequests;
|
||||||
|
break;
|
||||||
|
case 26: /* snmpOutGetNexts */
|
||||||
|
*uint_ptr = snmp_stats.outgetnexts;
|
||||||
|
break;
|
||||||
|
case 27: /* snmpOutSetRequests */
|
||||||
|
*uint_ptr = snmp_stats.outsetrequests;
|
||||||
|
break;
|
||||||
|
case 28: /* snmpOutGetResponses */
|
||||||
|
*uint_ptr = snmp_stats.outgetresponses;
|
||||||
|
break;
|
||||||
|
case 29: /* snmpOutTraps */
|
||||||
|
*uint_ptr = snmp_stats.outtraps;
|
||||||
|
break;
|
||||||
|
case 30: /* snmpEnableAuthenTraps */
|
||||||
|
if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) {
|
||||||
|
*uint_ptr = MIB2_AUTH_TRAPS_DISABLED;
|
||||||
|
} else {
|
||||||
|
*uint_ptr = MIB2_AUTH_TRAPS_ENABLED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 31: /* snmpSilentDrops */
|
||||||
|
*uint_ptr = 0; /* not supported */
|
||||||
|
break;
|
||||||
|
case 32: /* snmpProxyDrops */
|
||||||
|
*uint_ptr = 0; /* not supported */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
|
||||||
|
if (node->oid == 30) {
|
||||||
|
/* snmpEnableAuthenTraps */
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
|
||||||
|
/* we should have writable non-volatile mem here */
|
||||||
|
if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) {
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
|
||||||
|
if (node->oid == 30) {
|
||||||
|
/* snmpEnableAuthenTraps */
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) {
|
||||||
|
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED);
|
||||||
|
} else {
|
||||||
|
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */
|
||||||
|
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */
|
||||||
|
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */
|
||||||
|
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */
|
||||||
|
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */
|
||||||
|
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */
|
||||||
|
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */
|
||||||
|
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */
|
||||||
|
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */
|
||||||
|
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */
|
||||||
|
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */
|
||||||
|
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */
|
||||||
|
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */
|
||||||
|
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */
|
||||||
|
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */
|
||||||
|
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */
|
||||||
|
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */
|
||||||
|
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */
|
||||||
|
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */
|
||||||
|
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */
|
||||||
|
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */
|
||||||
|
{27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */
|
||||||
|
{28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */
|
||||||
|
{29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */
|
||||||
|
{30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */
|
||||||
|
{31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */
|
||||||
|
{32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value);
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
||||||
377
ext/lwip/src/apps/snmp/snmp_mib2_system.c
Executable file
377
ext/lwip/src/apps/snmp/snmp_mib2_system.c
Executable file
@@ -0,0 +1,377 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) SYSTEM objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
/** mib-2.system.sysDescr */
|
||||||
|
static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC;
|
||||||
|
static const u8_t* sysdescr = sysdescr_default;
|
||||||
|
static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */
|
||||||
|
|
||||||
|
/** mib-2.system.sysContact */
|
||||||
|
static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT;
|
||||||
|
static const u8_t* syscontact = syscontact_default;
|
||||||
|
static const u16_t* syscontact_len = NULL; /* use strlen for determining len */
|
||||||
|
static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */
|
||||||
|
static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */
|
||||||
|
static u16_t syscontact_bufsize = 0; /* 0=not writable */
|
||||||
|
|
||||||
|
/** mib-2.system.sysName */
|
||||||
|
static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME;
|
||||||
|
static const u8_t* sysname = sysname_default;
|
||||||
|
static const u16_t* sysname_len = NULL; /* use strlen for determining len */
|
||||||
|
static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */
|
||||||
|
static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */
|
||||||
|
static u16_t sysname_bufsize = 0; /* 0=not writable */
|
||||||
|
|
||||||
|
/** mib-2.system.sysLocation */
|
||||||
|
static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION;
|
||||||
|
static const u8_t* syslocation = syslocation_default;
|
||||||
|
static const u16_t* syslocation_len = NULL; /* use strlen for determining len */
|
||||||
|
static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */
|
||||||
|
static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */
|
||||||
|
static u16_t syslocation_bufsize = 0; /* 0=not writable */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* Initializes sysDescr pointers.
|
||||||
|
*
|
||||||
|
* @param str if non-NULL then copy str pointer
|
||||||
|
* @param len points to string length, excluding zero terminator
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len)
|
||||||
|
{
|
||||||
|
if (str != NULL) {
|
||||||
|
sysdescr = str;
|
||||||
|
sysdescr_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* Initializes sysContact pointers
|
||||||
|
*
|
||||||
|
* @param ocstr if non-NULL then copy str pointer
|
||||||
|
* @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)
|
||||||
|
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
|
||||||
|
* otherwise complete buffer is used for string.
|
||||||
|
* if bufsize is set to 0, the value is regarded as read-only.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
syscontact = ocstr;
|
||||||
|
syscontact_wr = ocstr;
|
||||||
|
syscontact_len = ocstrlen;
|
||||||
|
syscontact_wr_len = ocstrlen;
|
||||||
|
syscontact_bufsize = bufsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* see \ref snmp_mib2_set_syscontact but set pointer to readonly memory
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
syscontact = ocstr;
|
||||||
|
syscontact_len = ocstrlen;
|
||||||
|
syscontact_wr = NULL;
|
||||||
|
syscontact_wr_len = NULL;
|
||||||
|
syscontact_bufsize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* Initializes sysName pointers
|
||||||
|
*
|
||||||
|
* @param ocstr if non-NULL then copy str pointer
|
||||||
|
* @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)
|
||||||
|
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
|
||||||
|
* otherwise complete buffer is used for string.
|
||||||
|
* if bufsize is set to 0, the value is regarded as read-only.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
sysname = ocstr;
|
||||||
|
sysname_wr = ocstr;
|
||||||
|
sysname_len = ocstrlen;
|
||||||
|
sysname_wr_len = ocstrlen;
|
||||||
|
sysname_bufsize = bufsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* see \ref snmp_mib2_set_sysname but set pointer to readonly memory
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
sysname = ocstr;
|
||||||
|
sysname_len = ocstrlen;
|
||||||
|
sysname_wr = NULL;
|
||||||
|
sysname_wr_len = NULL;
|
||||||
|
sysname_bufsize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* Initializes sysLocation pointers
|
||||||
|
*
|
||||||
|
* @param ocstr if non-NULL then copy str pointer
|
||||||
|
* @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)
|
||||||
|
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
|
||||||
|
* otherwise complete buffer is used for string.
|
||||||
|
* if bufsize is set to 0, the value is regarded as read-only.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
syslocation = ocstr;
|
||||||
|
syslocation_wr = ocstr;
|
||||||
|
syslocation_len = ocstrlen;
|
||||||
|
syslocation_wr_len = ocstrlen;
|
||||||
|
syslocation_bufsize = bufsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_mib2
|
||||||
|
* see \ref snmp_mib2_set_syslocation but set pointer to readonly memory
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
|
||||||
|
{
|
||||||
|
if (ocstr != NULL) {
|
||||||
|
syslocation = ocstr;
|
||||||
|
syslocation_len = ocstrlen;
|
||||||
|
syslocation_wr = NULL;
|
||||||
|
syslocation_wr_len = NULL;
|
||||||
|
syslocation_bufsize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
system_get_value(const struct snmp_scalar_array_node_def *node, void *value)
|
||||||
|
{
|
||||||
|
const u8_t* var = NULL;
|
||||||
|
const s16_t* var_len;
|
||||||
|
u16_t result;
|
||||||
|
|
||||||
|
switch (node->oid) {
|
||||||
|
case 1: /* sysDescr */
|
||||||
|
var = sysdescr;
|
||||||
|
var_len = (const s16_t*)sysdescr_len;
|
||||||
|
break;
|
||||||
|
case 2: /* sysObjectID */
|
||||||
|
{
|
||||||
|
const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid();
|
||||||
|
MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t));
|
||||||
|
return dev_enterprise_oid->len * sizeof(u32_t);
|
||||||
|
}
|
||||||
|
case 3: /* sysUpTime */
|
||||||
|
MIB2_COPY_SYSUPTIME_TO((u32_t*)value);
|
||||||
|
return sizeof(u32_t);
|
||||||
|
case 4: /* sysContact */
|
||||||
|
var = syscontact;
|
||||||
|
var_len = (const s16_t*)syscontact_len;
|
||||||
|
break;
|
||||||
|
case 5: /* sysName */
|
||||||
|
var = sysname;
|
||||||
|
var_len = (const s16_t*)sysname_len;
|
||||||
|
break;
|
||||||
|
case 6: /* sysLocation */
|
||||||
|
var = syslocation;
|
||||||
|
var_len = (const s16_t*)syslocation_len;
|
||||||
|
break;
|
||||||
|
case 7: /* sysServices */
|
||||||
|
*(s32_t*)value = SNMP_SYSSERVICES;
|
||||||
|
return sizeof(s32_t);
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle string values (OID 1,4,5 and 6) */
|
||||||
|
LWIP_ASSERT("", (value != NULL));
|
||||||
|
if (var_len == NULL) {
|
||||||
|
result = (s16_t)strlen((const char*)var);
|
||||||
|
} else {
|
||||||
|
result = *var_len;
|
||||||
|
}
|
||||||
|
MEMCPY(value, var, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
const u16_t* var_bufsize = NULL;
|
||||||
|
const u16_t* var_wr_len;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value);
|
||||||
|
|
||||||
|
switch (node->oid) {
|
||||||
|
case 4: /* sysContact */
|
||||||
|
var_bufsize = &syscontact_bufsize;
|
||||||
|
var_wr_len = syscontact_wr_len;
|
||||||
|
break;
|
||||||
|
case 5: /* sysName */
|
||||||
|
var_bufsize = &sysname_bufsize;
|
||||||
|
var_wr_len = sysname_wr_len;
|
||||||
|
break;
|
||||||
|
case 6: /* sysLocation */
|
||||||
|
var_bufsize = &syslocation_bufsize;
|
||||||
|
var_wr_len = syslocation_wr_len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if value is writable at all */
|
||||||
|
if (*var_bufsize > 0) {
|
||||||
|
if (var_wr_len == NULL) {
|
||||||
|
/* we have to take the terminating 0 into account */
|
||||||
|
if (len < *var_bufsize) {
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (len <= *var_bufsize) {
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = SNMP_ERR_NOTWRITABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
u16_t* var_wr_len;
|
||||||
|
|
||||||
|
switch (node->oid) {
|
||||||
|
case 4: /* sysContact */
|
||||||
|
var_wr = syscontact_wr;
|
||||||
|
var_wr_len = syscontact_wr_len;
|
||||||
|
break;
|
||||||
|
case 5: /* sysName */
|
||||||
|
var_wr = sysname_wr;
|
||||||
|
var_wr_len = sysname_wr_len;
|
||||||
|
break;
|
||||||
|
case 6: /* sysLocation */
|
||||||
|
var_wr = syslocation_wr;
|
||||||
|
var_wr_len = syslocation_wr_len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid));
|
||||||
|
return SNMP_ERR_GENERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no need to check size of target buffer, this was already done in set_test method */
|
||||||
|
LWIP_ASSERT("", var_wr != NULL);
|
||||||
|
MEMCPY(var_wr, value, len);
|
||||||
|
|
||||||
|
if (var_wr_len == NULL) {
|
||||||
|
/* add terminating 0 */
|
||||||
|
var_wr[len] = 0;
|
||||||
|
} else {
|
||||||
|
*var_wr_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snmp_scalar_array_node_def system_nodes[] = {
|
||||||
|
{1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */
|
||||||
|
{2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */
|
||||||
|
{3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */
|
||||||
|
{4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */
|
||||||
|
{5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */
|
||||||
|
{6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */
|
||||||
|
{7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value);
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
||||||
594
ext/lwip/src/apps/snmp/snmp_mib2_tcp.c
Executable file
594
ext/lwip/src/apps/snmp/snmp_mib2_tcp.c
Executable file
@@ -0,0 +1,594 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) TCP objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
#include "lwip/priv/tcp_priv.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
tcp_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
u32_t *uint_ptr = (u32_t*)value;
|
||||||
|
s32_t *sint_ptr = (s32_t*)value;
|
||||||
|
|
||||||
|
switch (instance->node->oid) {
|
||||||
|
case 1: /* tcpRtoAlgorithm, vanj(4) */
|
||||||
|
*sint_ptr = 4;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 2: /* tcpRtoMin */
|
||||||
|
/* @todo not the actual value, a guess,
|
||||||
|
needs to be calculated */
|
||||||
|
*sint_ptr = 1000;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 3: /* tcpRtoMax */
|
||||||
|
/* @todo not the actual value, a guess,
|
||||||
|
needs to be calculated */
|
||||||
|
*sint_ptr = 60000;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 4: /* tcpMaxConn */
|
||||||
|
*sint_ptr = MEMP_NUM_TCP_PCB;
|
||||||
|
return sizeof(*sint_ptr);
|
||||||
|
case 5: /* tcpActiveOpens */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpactiveopens);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 6: /* tcpPassiveOpens */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcppassiveopens);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 7: /* tcpAttemptFails */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpattemptfails);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 8: /* tcpEstabResets */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpestabresets);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 9: /* tcpCurrEstab */
|
||||||
|
{
|
||||||
|
u16_t tcpcurrestab = 0;
|
||||||
|
struct tcp_pcb *pcb = tcp_active_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
if ((pcb->state == ESTABLISHED) ||
|
||||||
|
(pcb->state == CLOSE_WAIT)) {
|
||||||
|
tcpcurrestab++;
|
||||||
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
*uint_ptr = tcpcurrestab;
|
||||||
|
}
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 10: /* tcpInSegs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpinsegs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 11: /* tcpOutSegs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpoutsegs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 12: /* tcpRetransSegs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpretranssegs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 14: /* tcpInErrs */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpinerrs);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 15: /* tcpOutRsts */
|
||||||
|
*uint_ptr = STATS_GET(mib2.tcpoutrsts);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 17: /* tcpHCInSegs */
|
||||||
|
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
|
||||||
|
return 2*sizeof(u32_t);
|
||||||
|
case 18: /* tcpHCOutSegs */
|
||||||
|
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
|
||||||
|
return 2*sizeof(u32_t);
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- tcpConnTable --- */
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = {
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff }, /* IP D */
|
||||||
|
{ 0, 0xffff }, /* Port */
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff }, /* IP D */
|
||||||
|
{ 0, 0xffff } /* Port */
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
switch (*column) {
|
||||||
|
case 1: /* tcpConnState */
|
||||||
|
value->u32 = pcb->state + 1;
|
||||||
|
break;
|
||||||
|
case 2: /* tcpConnLocalAddress */
|
||||||
|
value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
|
||||||
|
break;
|
||||||
|
case 3: /* tcpConnLocalPort */
|
||||||
|
value->u32 = pcb->local_port;
|
||||||
|
break;
|
||||||
|
case 4: /* tcpConnRemAddress */
|
||||||
|
if (pcb->state == LISTEN) {
|
||||||
|
value->u32 = IP4_ADDR_ANY4->addr;
|
||||||
|
} else {
|
||||||
|
value->u32 = ip_2_ip4(&pcb->remote_ip)->addr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5: /* tcpConnRemPort */
|
||||||
|
if (pcb->state == LISTEN) {
|
||||||
|
value->u32 = 0;
|
||||||
|
} else {
|
||||||
|
value->u32 = pcb->remote_port;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_ASSERT("invalid id", 0);
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ConnTable_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)
|
||||||
|
{
|
||||||
|
u8_t i;
|
||||||
|
ip4_addr_t local_ip;
|
||||||
|
ip4_addr_t remote_ip;
|
||||||
|
u16_t local_port;
|
||||||
|
u16_t remote_port;
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get IPs and ports from incoming OID */
|
||||||
|
snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */
|
||||||
|
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];
|
||||||
|
|
||||||
|
while (pcb != NULL) {
|
||||||
|
/* do local IP and local port match? */
|
||||||
|
if (IP_IS_V4_VAL(pcb->local_ip) &&
|
||||||
|
ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) {
|
||||||
|
|
||||||
|
/* 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_ANY4) && (remote_port == 0)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IP_IS_V4_VAL(pcb->remote_ip) &&
|
||||||
|
ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
u8_t i;
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
|
||||||
|
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_ANY4, &test_oid[5]);
|
||||||
|
test_oid[9] = 0;
|
||||||
|
} else {
|
||||||
|
if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]);
|
||||||
|
test_oid[9] = pcb->remote_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
/* --- tcpConnectionTable --- */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
switch (*column) {
|
||||||
|
case 7: /* tcpConnectionState */
|
||||||
|
value->u32 = pcb->state + 1;
|
||||||
|
break;
|
||||||
|
case 8: /* tcpConnectionProcess */
|
||||||
|
value->u32 = 0; /* not supported */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ConnectionTable_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;
|
||||||
|
u16_t local_port, remote_port;
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
u8_t idx = 0;
|
||||||
|
u8_t i;
|
||||||
|
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
|
||||||
|
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
|
||||||
|
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) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) &&
|
||||||
|
ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
|
||||||
|
(remote_port == pcb->remote_port)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ConnectionTable_get_cell_value_core(column, pcb, value);
|
||||||
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
/* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort
|
||||||
|
* 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */
|
||||||
|
u32_t result_temp[38];
|
||||||
|
u8_t i;
|
||||||
|
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
|
||||||
|
pcb = *tcp_pcb_nonlisten_lists[i];
|
||||||
|
|
||||||
|
while (pcb != NULL) {
|
||||||
|
u8_t idx = 0;
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
|
||||||
|
|
||||||
|
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
|
||||||
|
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
|
||||||
|
|
||||||
|
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
|
||||||
|
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value);
|
||||||
|
} else {
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- tcpListenerTable --- */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
switch (*column) {
|
||||||
|
case 4: /* tcpListenerProcess */
|
||||||
|
value->u32 = 0; /* not supported */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ListenerTable_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;
|
||||||
|
u16_t local_port;
|
||||||
|
struct tcp_pcb_listen *pcb;
|
||||||
|
u8_t idx = 0;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
|
||||||
|
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
|
||||||
|
if (idx == 0) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find tcp_pcb with requested ip and port*/
|
||||||
|
pcb = tcp_listen_pcbs.listen_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
|
||||||
|
(local_port == pcb->local_port)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ListenerTable_get_cell_value_core(column, value);
|
||||||
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct tcp_pcb_listen *pcb;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
/* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */
|
||||||
|
u32_t result_temp[19];
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
pcb = tcp_listen_pcbs.listen_pcbs;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return tcp_ListenerTable_get_cell_value_core(column, value);
|
||||||
|
} else {
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
|
||||||
|
static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */
|
||||||
|
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */
|
||||||
|
{ 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */
|
||||||
|
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value);
|
||||||
|
#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 */
|
||||||
|
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */
|
||||||
|
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value);
|
||||||
|
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = {
|
||||||
|
/* 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 */
|
||||||
|
CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets)
|
||||||
|
CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab)
|
||||||
|
CREATE_LWIP_SYNC_NODE(10, tcp_InSegs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs)
|
||||||
|
#if LWIP_IPV4
|
||||||
|
CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable)
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
CREATE_LWIP_SYNC_NODE(14, tcp_InErrs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts)
|
||||||
|
CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs)
|
||||||
|
CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable)
|
||||||
|
CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable)
|
||||||
|
|
||||||
|
static const struct snmp_node* const tcp_nodes[] = {
|
||||||
|
&SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_RtoMin).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_RtoMax).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_MaxConn).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_ActiveOpens).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_PassiveOpens).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_AttemptFails).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_EstabResets).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_CurrEstab).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_InSegs).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_OutSegs).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_RetransSegs).node.node,
|
||||||
|
#if LWIP_IPV4
|
||||||
|
&SYNC_NODE_NAME(tcp_ConnTable).node.node,
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
&SYNC_NODE_NAME(tcp_InErrs).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_OutRsts).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_HCInSegs).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_HCOutSegs).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_ConnectionTable).node.node,
|
||||||
|
&SYNC_NODE_NAME(tcp_ListenerTable).node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes);
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */
|
||||||
357
ext/lwip/src/apps/snmp/snmp_mib2_udp.c
Executable file
357
ext/lwip/src/apps/snmp/snmp_mib2_udp.c
Executable file
@@ -0,0 +1,357 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Management Information Base II (RFC1213) UDP objects and functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_mib2.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP
|
||||||
|
|
||||||
|
#if SNMP_USE_NETCONN
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name ## _synced
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
||||||
|
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
||||||
|
#else
|
||||||
|
#define SYNC_NODE_NAME(node_name) node_name
|
||||||
|
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
udp_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
u32_t *uint_ptr = (u32_t*)value;
|
||||||
|
|
||||||
|
switch (instance->node->oid) {
|
||||||
|
case 1: /* udpInDatagrams */
|
||||||
|
*uint_ptr = STATS_GET(mib2.udpindatagrams);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 2: /* udpNoPorts */
|
||||||
|
*uint_ptr = STATS_GET(mib2.udpnoports);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 3: /* udpInErrors */
|
||||||
|
*uint_ptr = STATS_GET(mib2.udpinerrors);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 4: /* udpOutDatagrams */
|
||||||
|
*uint_ptr = STATS_GET(mib2.udpoutdatagrams);
|
||||||
|
return sizeof(*uint_ptr);
|
||||||
|
case 8: /* udpHCInDatagrams */
|
||||||
|
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
|
||||||
|
return 2*sizeof(u32_t);
|
||||||
|
case 9: /* udpHCOutDatagrams */
|
||||||
|
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
|
||||||
|
return 2*sizeof(u32_t);
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- udpEndpointTable --- */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
switch (*column) {
|
||||||
|
case 8: /* udpEndpointProcess */
|
||||||
|
value->u32 = 0; /* not supported */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
u16_t local_port, remote_port;
|
||||||
|
struct udp_pcb *pcb;
|
||||||
|
u8_t idx = 0;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
|
||||||
|
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
|
||||||
|
if (idx == 0) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
|
||||||
|
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
|
||||||
|
if (idx == 0) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* udpEndpointInstance */
|
||||||
|
if (row_oid_len < (idx+1)) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
if (row_oid[idx] != 0) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find udp_pcb with requested ip and port*/
|
||||||
|
pcb = udp_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
|
||||||
|
(local_port == pcb->local_port) &&
|
||||||
|
ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
|
||||||
|
(remote_port == pcb->remote_port)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return udp_endpointTable_get_cell_value_core(column, value);
|
||||||
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct udp_pcb *pcb;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
/* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort +
|
||||||
|
* 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort +
|
||||||
|
* 1x udpEndpointInstance = 39
|
||||||
|
*/
|
||||||
|
u32_t result_temp[39];
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
pcb = udp_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
|
||||||
|
u8_t idx = 0;
|
||||||
|
|
||||||
|
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
|
||||||
|
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
|
||||||
|
|
||||||
|
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
|
||||||
|
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
|
||||||
|
|
||||||
|
test_oid[idx] = 0; /* udpEndpointInstance */
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
|
snmp_next_oid_check(&state, test_oid, idx, NULL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return udp_endpointTable_get_cell_value_core(column, value);
|
||||||
|
} else {
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- udpTable --- */
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
|
||||||
|
/* list of allowed value ranges for incoming OID */
|
||||||
|
static const struct snmp_oid_range udp_Table_oid_ranges[] = {
|
||||||
|
{ 0, 0xff }, /* IP A */
|
||||||
|
{ 0, 0xff }, /* IP B */
|
||||||
|
{ 0, 0xff }, /* IP C */
|
||||||
|
{ 0, 0xff }, /* IP D */
|
||||||
|
{ 1, 0xffff } /* Port */
|
||||||
|
};
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(value_len);
|
||||||
|
|
||||||
|
switch (*column) {
|
||||||
|
case 1: /* udpLocalAddress */
|
||||||
|
/* set reference to PCB local IP and return a generic node that copies IP4 addresses */
|
||||||
|
value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
|
||||||
|
break;
|
||||||
|
case 2: /* udpLocalPort */
|
||||||
|
/* set reference to PCB local port and return a generic node that copies u16_t values */
|
||||||
|
value->u32 = pcb->local_port;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
udp_Table_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)
|
||||||
|
{
|
||||||
|
ip4_addr_t ip;
|
||||||
|
u16_t port;
|
||||||
|
struct udp_pcb *pcb;
|
||||||
|
|
||||||
|
/* check if incoming OID length and if values are in plausible range */
|
||||||
|
if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get IP and port from incoming OID */
|
||||||
|
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
|
||||||
|
port = (u16_t)row_oid[4];
|
||||||
|
|
||||||
|
/* find udp_pcb with requested ip and port*/
|
||||||
|
pcb = udp_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
if (IP_IS_V4_VAL(pcb->local_ip)) {
|
||||||
|
if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) {
|
||||||
|
/* fill in object properties */
|
||||||
|
return udp_Table_get_cell_value_core(pcb, column, value, value_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
|
||||||
|
{
|
||||||
|
struct udp_pcb *pcb;
|
||||||
|
struct snmp_next_oid_state state;
|
||||||
|
u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
|
||||||
|
|
||||||
|
/* init struct to search next oid */
|
||||||
|
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges));
|
||||||
|
|
||||||
|
/* iterate over all possible OIDs to find the next one */
|
||||||
|
pcb = udp_pcbs;
|
||||||
|
while (pcb != NULL) {
|
||||||
|
u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_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;
|
||||||
|
|
||||||
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
|
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), 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);
|
||||||
|
/* fill in object properties */
|
||||||
|
return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len);
|
||||||
|
} else {
|
||||||
|
/* not found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
|
||||||
|
static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
|
||||||
|
static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
|
||||||
|
static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
|
||||||
|
static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
|
||||||
|
static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
static const struct snmp_table_simple_col_def udp_Table_columns[] = {
|
||||||
|
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */
|
||||||
|
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */
|
||||||
|
};
|
||||||
|
static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value);
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = {
|
||||||
|
/* all items except udpEndpointProcess are declared as not-accessible */
|
||||||
|
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_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 */
|
||||||
|
CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams)
|
||||||
|
CREATE_LWIP_SYNC_NODE(2, udp_noPorts)
|
||||||
|
CREATE_LWIP_SYNC_NODE(3, udp_inErrors)
|
||||||
|
CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams)
|
||||||
|
#if LWIP_IPV4
|
||||||
|
CREATE_LWIP_SYNC_NODE(5, udp_Table)
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
CREATE_LWIP_SYNC_NODE(7, udp_endpointTable)
|
||||||
|
CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams)
|
||||||
|
CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams)
|
||||||
|
|
||||||
|
static const struct snmp_node* const udp_nodes[] = {
|
||||||
|
&SYNC_NODE_NAME(udp_inDatagrams).node.node,
|
||||||
|
&SYNC_NODE_NAME(udp_noPorts).node.node,
|
||||||
|
&SYNC_NODE_NAME(udp_inErrors).node.node,
|
||||||
|
&SYNC_NODE_NAME(udp_outDatagrams).node.node,
|
||||||
|
#if LWIP_IPV4
|
||||||
|
&SYNC_NODE_NAME(udp_Table).node.node,
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
&SYNC_NODE_NAME(udp_endpointTable).node.node,
|
||||||
|
&SYNC_NODE_NAME(udp_HCInDatagrams).node.node,
|
||||||
|
&SYNC_NODE_NAME(udp_HCOutDatagrams).node.node
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes);
|
||||||
|
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */
|
||||||
1668
ext/lwip/src/apps/snmp/snmp_msg.c
Executable file
1668
ext/lwip/src/apps/snmp/snmp_msg.c
Executable file
File diff suppressed because it is too large
Load Diff
194
ext/lwip/src/apps/snmp/snmp_msg.h
Executable file
194
ext/lwip/src/apps/snmp/snmp_msg.h
Executable file
@@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP Agent message handling structures (internal API, do not use in client code).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||||
|
* Copyright (c) 2016 Elias Oenal.
|
||||||
|
* 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: Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
* Martin Hentschel <info@cl-soft.de>
|
||||||
|
* Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIP_HDR_APPS_SNMP_MSG_H
|
||||||
|
#define LWIP_HDR_APPS_SNMP_MSG_H
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "snmp_pbuf_stream.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP_V3
|
||||||
|
#include "snmpv3_priv.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The listen port of the SNMP agent. Clients have to make their requests to
|
||||||
|
this port. Most standard clients won't work if you change this! */
|
||||||
|
#ifndef SNMP_IN_PORT
|
||||||
|
#define SNMP_IN_PORT 161
|
||||||
|
#endif
|
||||||
|
/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't
|
||||||
|
work if you change this! */
|
||||||
|
#ifndef SNMP_TRAP_PORT
|
||||||
|
#define SNMP_TRAP_PORT 162
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* version defines used in PDU */
|
||||||
|
#define SNMP_VERSION_1 0
|
||||||
|
#define SNMP_VERSION_2c 1
|
||||||
|
#define SNMP_VERSION_3 3
|
||||||
|
|
||||||
|
struct snmp_varbind_enumerator
|
||||||
|
{
|
||||||
|
struct snmp_pbuf_stream pbuf_stream;
|
||||||
|
u16_t varbind_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct snmp_request
|
||||||
|
{
|
||||||
|
/* Communication handle */
|
||||||
|
void *handle;
|
||||||
|
/* source IP address */
|
||||||
|
const ip_addr_t *source_ip;
|
||||||
|
/* source UDP port */
|
||||||
|
u16_t source_port;
|
||||||
|
/* incoming snmp version */
|
||||||
|
u8_t version;
|
||||||
|
/* community name (zero terminated) */
|
||||||
|
u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1];
|
||||||
|
/* community string length (exclusive zero term) */
|
||||||
|
u16_t community_strlen;
|
||||||
|
/* request type */
|
||||||
|
u8_t request_type;
|
||||||
|
/* request ID */
|
||||||
|
s32_t request_id;
|
||||||
|
/* error status */
|
||||||
|
s32_t error_status;
|
||||||
|
/* error index */
|
||||||
|
s32_t error_index;
|
||||||
|
/* non-repeaters (getBulkRequest (SNMPv2c)) */
|
||||||
|
s32_t non_repeaters;
|
||||||
|
/* max-repetitions (getBulkRequest (SNMPv2c)) */
|
||||||
|
s32_t max_repetitions;
|
||||||
|
|
||||||
|
#if LWIP_SNMP_V3
|
||||||
|
s32_t msg_id;
|
||||||
|
s32_t msg_max_size;
|
||||||
|
u8_t msg_flags;
|
||||||
|
s32_t msg_security_model;
|
||||||
|
u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH];
|
||||||
|
u8_t msg_authoritative_engine_id_len;
|
||||||
|
s32_t msg_authoritative_engine_boots;
|
||||||
|
s32_t msg_authoritative_engine_time;
|
||||||
|
u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH];
|
||||||
|
u8_t msg_user_name_len;
|
||||||
|
u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH];
|
||||||
|
u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH];
|
||||||
|
u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH];
|
||||||
|
u8_t context_engine_id_len;
|
||||||
|
u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH];
|
||||||
|
u8_t context_name_len;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct pbuf *inbound_pbuf;
|
||||||
|
struct snmp_varbind_enumerator inbound_varbind_enumerator;
|
||||||
|
u16_t inbound_varbind_offset;
|
||||||
|
u16_t inbound_varbind_len;
|
||||||
|
u16_t inbound_padding_len;
|
||||||
|
|
||||||
|
struct pbuf *outbound_pbuf;
|
||||||
|
struct snmp_pbuf_stream outbound_pbuf_stream;
|
||||||
|
u16_t outbound_pdu_offset;
|
||||||
|
u16_t outbound_error_status_offset;
|
||||||
|
u16_t outbound_error_index_offset;
|
||||||
|
u16_t outbound_varbind_offset;
|
||||||
|
#if LWIP_SNMP_V3
|
||||||
|
u16_t outbound_msg_global_data_offset;
|
||||||
|
u16_t outbound_msg_global_data_end;
|
||||||
|
u16_t outbound_msg_security_parameters_str_offset;
|
||||||
|
u16_t outbound_msg_security_parameters_seq_offset;
|
||||||
|
u16_t outbound_msg_security_parameters_end;
|
||||||
|
u16_t outbound_msg_authentication_parameters_offset;
|
||||||
|
u16_t outbound_scoped_pdu_seq_offset;
|
||||||
|
u16_t outbound_scoped_pdu_string_offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u8_t value_buffer[SNMP_MAX_VALUE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A helper struct keeping length information about varbinds */
|
||||||
|
struct snmp_varbind_len
|
||||||
|
{
|
||||||
|
u8_t vb_len_len;
|
||||||
|
u16_t vb_value_len;
|
||||||
|
u8_t oid_len_len;
|
||||||
|
u16_t oid_value_len;
|
||||||
|
u8_t value_len_len;
|
||||||
|
u16_t value_value_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Agent community string */
|
||||||
|
extern const char *snmp_community;
|
||||||
|
/** Agent community string for write access */
|
||||||
|
extern const char *snmp_community_write;
|
||||||
|
/** handle for sending traps */
|
||||||
|
extern void* snmp_traps_handle;
|
||||||
|
|
||||||
|
void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port);
|
||||||
|
err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port);
|
||||||
|
u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result);
|
||||||
|
err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len);
|
||||||
|
err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_SNMP_MSG_H */
|
||||||
121
ext/lwip/src/apps/snmp/snmp_netconn.c
Executable file
121
ext/lwip/src/apps/snmp/snmp_netconn.c
Executable file
@@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP netconn frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_USE_NETCONN
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "lwip/api.h"
|
||||||
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "snmp_msg.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
/** SNMP netconn API worker thread */
|
||||||
|
static void
|
||||||
|
snmp_netconn_thread(void *arg)
|
||||||
|
{
|
||||||
|
struct netconn *conn;
|
||||||
|
struct netbuf *buf;
|
||||||
|
err_t err;
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
/* Bind to SNMP port with default IP address */
|
||||||
|
#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, IP4_ADDR_ANY, SNMP_IN_PORT);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;);
|
||||||
|
|
||||||
|
snmp_traps_handle = conn;
|
||||||
|
|
||||||
|
do {
|
||||||
|
err = netconn_recv(conn, &buf);
|
||||||
|
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
snmp_receive(conn, buf->p, &buf->addr, buf->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL) {
|
||||||
|
netbuf_delete(buf);
|
||||||
|
}
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port)
|
||||||
|
{
|
||||||
|
err_t result;
|
||||||
|
struct netbuf buf;
|
||||||
|
|
||||||
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
buf.p = p;
|
||||||
|
result = netconn_sendto((struct netconn*)handle, &buf, dst, port);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8_t
|
||||||
|
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result)
|
||||||
|
{
|
||||||
|
struct netconn* conn = (struct netconn*)handle;
|
||||||
|
struct netif *dst_if;
|
||||||
|
const ip_addr_t* dst_ip;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */
|
||||||
|
|
||||||
|
ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip);
|
||||||
|
|
||||||
|
if ((dst_if != NULL) && (dst_ip != NULL)) {
|
||||||
|
ip_addr_copy(*result, *dst_ip);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts SNMP Agent.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_init(void)
|
||||||
|
{
|
||||||
|
sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_USE_NETCONN */
|
||||||
156
ext/lwip/src/apps/snmp/snmp_pbuf_stream.c
Executable file
156
ext/lwip/src/apps/snmp/snmp_pbuf_stream.c
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP pbuf stream wrapper implementation (internal API, do not use in client code).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel <info@cl-soft.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "snmp_pbuf_stream.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length)
|
||||||
|
{
|
||||||
|
pbuf_stream->offset = offset;
|
||||||
|
pbuf_stream->length = length;
|
||||||
|
pbuf_stream->pbuf = p;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data)
|
||||||
|
{
|
||||||
|
if (pbuf_stream->length == 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_stream->offset++;
|
||||||
|
pbuf_stream->length--;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data)
|
||||||
|
{
|
||||||
|
return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len)
|
||||||
|
{
|
||||||
|
if (pbuf_stream->length < buf_len) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_stream->offset += buf_len;
|
||||||
|
pbuf_stream->length -= buf_len;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
u16_t chunk_len;
|
||||||
|
err_t err;
|
||||||
|
u16_t target_offset;
|
||||||
|
struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset);
|
||||||
|
|
||||||
|
if ((pbuf == NULL) || (pbuf->len == 0)) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_len = LWIP_MIN(len, pbuf->len);
|
||||||
|
err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_stream->offset += chunk_len;
|
||||||
|
pbuf_stream->length -= chunk_len;
|
||||||
|
len -= chunk_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset)
|
||||||
|
{
|
||||||
|
if ((offset < 0) || (offset > pbuf_stream->length)) {
|
||||||
|
/* we cannot seek backwards or forward behind stream end */
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_stream->offset += (u16_t)offset;
|
||||||
|
pbuf_stream->length -= (u16_t)offset;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset)
|
||||||
|
{
|
||||||
|
s32_t rel_offset = offset - pbuf_stream->offset;
|
||||||
|
return snmp_pbuf_stream_seek(pbuf_stream, rel_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
73
ext/lwip/src/apps/snmp/snmp_pbuf_stream.h
Executable file
73
ext/lwip/src/apps/snmp/snmp_pbuf_stream.h
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP pbuf stream wrapper (internal API, do not use in client code).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel <info@cl-soft.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H
|
||||||
|
#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct snmp_pbuf_stream
|
||||||
|
{
|
||||||
|
struct pbuf* pbuf;
|
||||||
|
u16_t offset;
|
||||||
|
u16_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length);
|
||||||
|
err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data);
|
||||||
|
err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data);
|
||||||
|
err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len);
|
||||||
|
err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len);
|
||||||
|
err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset);
|
||||||
|
err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */
|
||||||
100
ext/lwip/src/apps/snmp/snmp_raw.c
Executable file
100
ext/lwip/src/apps/snmp/snmp_raw.c
Executable file
@@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP RAW API frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && SNMP_USE_RAW
|
||||||
|
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/ip.h"
|
||||||
|
#include "snmp_msg.h"
|
||||||
|
|
||||||
|
/* lwIP UDP receive callback function */
|
||||||
|
static void
|
||||||
|
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
snmp_receive(pcb, p, addr, port);
|
||||||
|
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port)
|
||||||
|
{
|
||||||
|
return udp_sendto((struct udp_pcb*)handle, p, dst, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8_t
|
||||||
|
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result)
|
||||||
|
{
|
||||||
|
struct udp_pcb* udp_pcb = (struct udp_pcb*)handle;
|
||||||
|
struct netif *dst_if;
|
||||||
|
const ip_addr_t* dst_ip;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */
|
||||||
|
|
||||||
|
ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip);
|
||||||
|
|
||||||
|
if ((dst_if != NULL) && (dst_ip != NULL)) {
|
||||||
|
ip_addr_copy(*result, *dst_ip);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_core
|
||||||
|
* Starts SNMP Agent.
|
||||||
|
* Allocates UDP pcb and binds it to IP_ANY_TYPE port 161.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_init(void)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||||
|
LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;);
|
||||||
|
|
||||||
|
snmp_traps_handle = snmp_pcb;
|
||||||
|
|
||||||
|
udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT);
|
||||||
|
err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT);
|
||||||
|
LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && SNMP_USE_RAW */
|
||||||
220
ext/lwip/src/apps/snmp/snmp_scalar.c
Executable file
220
ext/lwip/src/apps/snmp/snmp_scalar.c
Executable file
@@ -0,0 +1,220 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP scalar node support implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel <info@cl-soft.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_scalar.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
|
||||||
|
static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value);
|
||||||
|
static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value);
|
||||||
|
static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value);
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
/* scalar only has one dedicated instance: .0 */
|
||||||
|
if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->access = scalar_node->access;
|
||||||
|
instance->asn1_type = scalar_node->asn1_type;
|
||||||
|
instance->get_value = scalar_node->get_value;
|
||||||
|
instance->set_test = scalar_node->set_test;
|
||||||
|
instance->set_value = scalar_node->set_value;
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
/* because our only instance is .0 we can only return a next instance if no instance oid is passed */
|
||||||
|
if (instance->instance_oid.len == 0) {
|
||||||
|
instance->instance_oid.len = 1;
|
||||||
|
instance->instance_oid.id[0] = 0;
|
||||||
|
|
||||||
|
return snmp_scalar_get_instance(root_oid, root_oid_len, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) {
|
||||||
|
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes;
|
||||||
|
u32_t i = 0;
|
||||||
|
|
||||||
|
while (i < array_node->array_node_count) {
|
||||||
|
if (array_node_def->oid == instance->instance_oid.id[0]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_node_def++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < array_node->array_node_count) {
|
||||||
|
instance->access = array_node_def->access;
|
||||||
|
instance->asn1_type = array_node_def->asn1_type;
|
||||||
|
instance->get_value = snmp_scalar_array_get_value;
|
||||||
|
instance->set_test = snmp_scalar_array_set_test;
|
||||||
|
instance->set_value = snmp_scalar_array_set_value;
|
||||||
|
instance->reference.const_ptr = array_node_def;
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes;
|
||||||
|
const struct snmp_scalar_array_node_def* result = NULL;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) {
|
||||||
|
/* return node with lowest OID */
|
||||||
|
u16_t i = 0;
|
||||||
|
|
||||||
|
result = array_node_def;
|
||||||
|
array_node_def++;
|
||||||
|
|
||||||
|
for (i = 1; i < array_node->array_node_count; i++) {
|
||||||
|
if (array_node_def->oid < result->oid) {
|
||||||
|
result = array_node_def;
|
||||||
|
}
|
||||||
|
array_node_def++;
|
||||||
|
}
|
||||||
|
} else if (instance->instance_oid.len >= 1) {
|
||||||
|
if (instance->instance_oid.len == 1) {
|
||||||
|
/* if we have the requested OID we return its instance, otherwise we search for the next available */
|
||||||
|
u16_t i = 0;
|
||||||
|
while (i < array_node->array_node_count) {
|
||||||
|
if (array_node_def->oid == instance->instance_oid.id[0]) {
|
||||||
|
result = array_node_def;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_node_def++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == NULL) {
|
||||||
|
u32_t oid_dist = 0xFFFFFFFFUL;
|
||||||
|
u16_t i = 0;
|
||||||
|
array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */
|
||||||
|
while (i < array_node->array_node_count) {
|
||||||
|
if ((array_node_def->oid > instance->instance_oid.id[0]) &&
|
||||||
|
((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) {
|
||||||
|
result = array_node_def;
|
||||||
|
oid_dist = array_node_def->oid - instance->instance_oid.id[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
array_node_def++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
/* nothing to return */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->instance_oid.len = 2;
|
||||||
|
instance->instance_oid.id[0] = result->oid;
|
||||||
|
instance->instance_oid.id[1] = 0;
|
||||||
|
|
||||||
|
instance->access = result->access;
|
||||||
|
instance->asn1_type = result->asn1_type;
|
||||||
|
instance->get_value = snmp_scalar_array_get_value;
|
||||||
|
instance->set_test = snmp_scalar_array_set_test;
|
||||||
|
instance->set_value = snmp_scalar_array_set_value;
|
||||||
|
instance->reference.const_ptr = result;
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr;
|
||||||
|
|
||||||
|
return array_node->get_value(array_node_def, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value)
|
||||||
|
{
|
||||||
|
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr;
|
||||||
|
|
||||||
|
return array_node->set_test(array_node_def, value_len, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value)
|
||||||
|
{
|
||||||
|
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr;
|
||||||
|
|
||||||
|
return array_node->set_value(array_node_def, value_len, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
343
ext/lwip/src/apps/snmp/snmp_table.c
Executable file
343
ext/lwip/src/apps/snmp/snmp_table.c
Executable file
@@ -0,0 +1,343 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP table support implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel <info@cl-soft.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/apps/snmp_table.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
|
||||||
|
/* fixed row entry always has oid 1 */
|
||||||
|
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
|
||||||
|
/* search column */
|
||||||
|
const struct snmp_table_col_def* col_def = table_node->columns;
|
||||||
|
u16_t i = table_node->column_count;
|
||||||
|
while (i > 0) {
|
||||||
|
if (col_def->index == instance->instance_oid.id[1]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
col_def++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
/* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */
|
||||||
|
instance->asn1_type = col_def->asn1_type;
|
||||||
|
instance->access = col_def->access;
|
||||||
|
instance->get_value = table_node->get_value;
|
||||||
|
instance->set_test = table_node->set_test;
|
||||||
|
instance->set_value = table_node->set_value;
|
||||||
|
|
||||||
|
ret = table_node->get_cell_instance(
|
||||||
|
&(instance->instance_oid.id[1]),
|
||||||
|
&(instance->instance_oid.id[2]),
|
||||||
|
instance->instance_oid.len-2,
|
||||||
|
instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_table_col_def* col_def;
|
||||||
|
struct snmp_obj_id row_oid;
|
||||||
|
u32_t column = 0;
|
||||||
|
snmp_err_t result;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
/* check that first part of id is 0 or 1, referencing fixed row entry */
|
||||||
|
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
if (instance->instance_oid.len > 1) {
|
||||||
|
column = instance->instance_oid.id[1];
|
||||||
|
}
|
||||||
|
if (instance->instance_oid.len > 2) {
|
||||||
|
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
|
||||||
|
} else {
|
||||||
|
row_oid.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->get_value = table_node->get_value;
|
||||||
|
instance->set_test = table_node->set_test;
|
||||||
|
instance->set_value = table_node->set_value;
|
||||||
|
|
||||||
|
/* resolve column and value */
|
||||||
|
do {
|
||||||
|
u16_t i;
|
||||||
|
const struct snmp_table_col_def* next_col_def = NULL;
|
||||||
|
col_def = table_node->columns;
|
||||||
|
|
||||||
|
for (i = 0; i < table_node->column_count; i++) {
|
||||||
|
if (col_def->index == column) {
|
||||||
|
next_col_def = col_def;
|
||||||
|
break;
|
||||||
|
} else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) {
|
||||||
|
next_col_def = col_def;
|
||||||
|
}
|
||||||
|
col_def++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_col_def == NULL) {
|
||||||
|
/* no further column found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->asn1_type = next_col_def->asn1_type;
|
||||||
|
instance->access = next_col_def->access;
|
||||||
|
|
||||||
|
result = table_node->get_next_cell_instance(
|
||||||
|
&next_col_def->index,
|
||||||
|
&row_oid,
|
||||||
|
instance);
|
||||||
|
|
||||||
|
if (result == SNMP_ERR_NOERROR) {
|
||||||
|
col_def = next_col_def;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
|
||||||
|
column = next_col_def->index + 1;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
/* build resulting oid */
|
||||||
|
instance->instance_oid.len = 2;
|
||||||
|
instance->instance_oid.id[0] = 1;
|
||||||
|
instance->instance_oid.id[1] = col_def->index;
|
||||||
|
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
|
||||||
|
/* fixed row entry always has oid 1 */
|
||||||
|
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
|
||||||
|
ret = table_node->get_cell_value(
|
||||||
|
&(instance->instance_oid.id[1]),
|
||||||
|
&(instance->instance_oid.id[2]),
|
||||||
|
instance->instance_oid.len-2,
|
||||||
|
&instance->reference,
|
||||||
|
&instance->reference_len);
|
||||||
|
|
||||||
|
if (ret == SNMP_ERR_NOERROR) {
|
||||||
|
/* search column */
|
||||||
|
const struct snmp_table_simple_col_def* col_def = table_node->columns;
|
||||||
|
u32_t i = table_node->column_count;
|
||||||
|
while (i > 0) {
|
||||||
|
if (col_def->index == instance->instance_oid.id[1]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
col_def++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
instance->asn1_type = col_def->asn1_type;
|
||||||
|
instance->access = SNMP_NODE_INSTANCE_READ_ONLY;
|
||||||
|
instance->set_test = NULL;
|
||||||
|
instance->set_value = NULL;
|
||||||
|
|
||||||
|
switch (col_def->data_type) {
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_U32:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_u32ref;
|
||||||
|
break;
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_S32:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_s32ref;
|
||||||
|
break;
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_refconstptr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
|
||||||
|
return SNMP_ERR_GENERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SNMP_ERR_NOERROR;
|
||||||
|
} else {
|
||||||
|
ret = SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node;
|
||||||
|
const struct snmp_table_simple_col_def* col_def;
|
||||||
|
struct snmp_obj_id row_oid;
|
||||||
|
u32_t column = 0;
|
||||||
|
snmp_err_t result;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(root_oid);
|
||||||
|
LWIP_UNUSED_ARG(root_oid_len);
|
||||||
|
|
||||||
|
/* check that first part of id is 0 or 1, referencing fixed row entry */
|
||||||
|
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
if (instance->instance_oid.len > 1) {
|
||||||
|
column = instance->instance_oid.id[1];
|
||||||
|
}
|
||||||
|
if (instance->instance_oid.len > 2) {
|
||||||
|
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
|
||||||
|
} else {
|
||||||
|
row_oid.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resolve column and value */
|
||||||
|
do {
|
||||||
|
u32_t i;
|
||||||
|
const struct snmp_table_simple_col_def* next_col_def = NULL;
|
||||||
|
col_def = table_node->columns;
|
||||||
|
|
||||||
|
for (i = 0; i < table_node->column_count; i++) {
|
||||||
|
if (col_def->index == column) {
|
||||||
|
next_col_def = col_def;
|
||||||
|
break;
|
||||||
|
} else if ((col_def->index > column) && ((next_col_def == NULL) ||
|
||||||
|
(col_def->index < next_col_def->index))) {
|
||||||
|
next_col_def = col_def;
|
||||||
|
}
|
||||||
|
col_def++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_col_def == NULL) {
|
||||||
|
/* no further column found */
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = table_node->get_next_cell_instance_and_value(
|
||||||
|
&next_col_def->index,
|
||||||
|
&row_oid,
|
||||||
|
&instance->reference,
|
||||||
|
&instance->reference_len);
|
||||||
|
|
||||||
|
if (result == SNMP_ERR_NOERROR) {
|
||||||
|
col_def = next_col_def;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
|
||||||
|
column = next_col_def->index + 1;
|
||||||
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
instance->asn1_type = col_def->asn1_type;
|
||||||
|
instance->access = SNMP_NODE_INSTANCE_READ_ONLY;
|
||||||
|
instance->set_test = NULL;
|
||||||
|
instance->set_value = NULL;
|
||||||
|
|
||||||
|
switch (col_def->data_type) {
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_U32:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_u32ref;
|
||||||
|
break;
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_S32:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_s32ref;
|
||||||
|
break;
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
|
||||||
|
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
|
||||||
|
instance->get_value = snmp_table_extract_value_from_refconstptr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
|
||||||
|
return SNMP_ERR_GENERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build resulting oid */
|
||||||
|
instance->instance_oid.len = 2;
|
||||||
|
instance->instance_oid.id[0] = 1;
|
||||||
|
instance->instance_oid.id[1] = col_def->index;
|
||||||
|
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
|
||||||
|
|
||||||
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s16_t
|
||||||
|
snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
s32_t *dst = (s32_t*)value;
|
||||||
|
*dst = instance->reference.s32;
|
||||||
|
return sizeof(*dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
s16_t
|
||||||
|
snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
u32_t *dst = (u32_t*)value;
|
||||||
|
*dst = instance->reference.u32;
|
||||||
|
return sizeof(*dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
s16_t
|
||||||
|
snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
MEMCPY(value, instance->reference.const_ptr, instance->reference_len);
|
||||||
|
return (u16_t)instance->reference_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
219
ext/lwip/src/apps/snmp/snmp_threadsync.c
Executable file
219
ext/lwip/src/apps/snmp/snmp_threadsync.c
Executable file
@@ -0,0 +1,219 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMP thread synchronization implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_threadsync.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn)
|
||||||
|
{
|
||||||
|
sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex);
|
||||||
|
call_data->threadsync_node->instance->sync_fn(fn, call_data);
|
||||||
|
sys_sem_wait(&call_data->threadsync_node->instance->sem);
|
||||||
|
sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
threadsync_get_value_synced(void *ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
|
||||||
|
call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s16_t
|
||||||
|
threadsync_get_value(struct snmp_node_instance* instance, void* value)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
|
||||||
|
|
||||||
|
call_data->arg1.value = value;
|
||||||
|
call_synced_function(call_data, threadsync_get_value_synced);
|
||||||
|
|
||||||
|
return call_data->retval.s16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
threadsync_set_test_synced(void *ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
|
||||||
|
call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
|
||||||
|
|
||||||
|
call_data->arg1.value = value;
|
||||||
|
call_data->arg2.len = len;
|
||||||
|
call_synced_function(call_data, threadsync_set_test_synced);
|
||||||
|
|
||||||
|
return call_data->retval.err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
threadsync_set_value_synced(void *ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
|
||||||
|
call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
|
||||||
|
|
||||||
|
call_data->arg1.value = value;
|
||||||
|
call_data->arg2.len = len;
|
||||||
|
call_synced_function(call_data, threadsync_set_value_synced);
|
||||||
|
|
||||||
|
return call_data->retval.err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
threadsync_release_instance_synced(void* ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
|
||||||
|
call_data->proxy_instance.release_instance(&call_data->proxy_instance);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
threadsync_release_instance(struct snmp_node_instance *instance)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
|
||||||
|
|
||||||
|
if (call_data->proxy_instance.release_instance != NULL) {
|
||||||
|
call_synced_function(call_data, threadsync_release_instance_synced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_instance_synced(void* ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
|
||||||
|
|
||||||
|
call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_next_instance_synced(void* ctx)
|
||||||
|
{
|
||||||
|
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
|
||||||
|
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
|
||||||
|
|
||||||
|
call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
|
||||||
|
|
||||||
|
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static snmp_err_t
|
||||||
|
do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn)
|
||||||
|
{
|
||||||
|
const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node;
|
||||||
|
struct threadsync_data *call_data = &threadsync_node->instance->data;
|
||||||
|
|
||||||
|
if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) {
|
||||||
|
LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID"));
|
||||||
|
return SNMP_ERR_NOSUCHINSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance));
|
||||||
|
|
||||||
|
instance->reference.ptr = call_data;
|
||||||
|
snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len);
|
||||||
|
|
||||||
|
call_data->proxy_instance.node = &threadsync_node->target->node;
|
||||||
|
call_data->threadsync_node = threadsync_node;
|
||||||
|
|
||||||
|
call_data->arg1.root_oid = root_oid;
|
||||||
|
call_data->arg2.root_oid_len = root_oid_len;
|
||||||
|
call_synced_function(call_data, fn);
|
||||||
|
|
||||||
|
if (call_data->retval.err == SNMP_ERR_NOERROR) {
|
||||||
|
instance->access = call_data->proxy_instance.access;
|
||||||
|
instance->asn1_type = call_data->proxy_instance.asn1_type;
|
||||||
|
instance->release_instance = threadsync_release_instance;
|
||||||
|
instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL;
|
||||||
|
instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL;
|
||||||
|
instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL;
|
||||||
|
snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return call_data->retval.err;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
return do_sync(root_oid, root_oid_len, instance, get_instance_synced);
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_err_t
|
||||||
|
snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
|
||||||
|
{
|
||||||
|
return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializes thread synchronization instance */
|
||||||
|
void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
445
ext/lwip/src/apps/snmp/snmp_traps.c
Executable file
445
ext/lwip/src/apps/snmp/snmp_traps.c
Executable file
@@ -0,0 +1,445 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMPv1 traps implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Martin Hentschel
|
||||||
|
* Christiaan Simons <christiaan.simons@axon.tv>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "lwip/apps/snmp.h"
|
||||||
|
#include "lwip/apps/snmp_core.h"
|
||||||
|
#include "snmp_msg.h"
|
||||||
|
#include "snmp_asn1.h"
|
||||||
|
#include "snmp_core_priv.h"
|
||||||
|
|
||||||
|
struct snmp_msg_trap
|
||||||
|
{
|
||||||
|
/* source enterprise ID (sysObjectID) */
|
||||||
|
const struct snmp_obj_id *enterprise;
|
||||||
|
/* source IP address, raw network order format */
|
||||||
|
ip_addr_t sip;
|
||||||
|
/* generic trap code */
|
||||||
|
u32_t gen_trap;
|
||||||
|
/* specific trap code */
|
||||||
|
u32_t spc_trap;
|
||||||
|
/* timestamp */
|
||||||
|
u32_t ts;
|
||||||
|
/* snmp_version */
|
||||||
|
u32_t snmp_version;
|
||||||
|
|
||||||
|
/* output trap lengths used in ASN encoding */
|
||||||
|
/* encoding pdu length */
|
||||||
|
u16_t pdulen;
|
||||||
|
/* encoding community length */
|
||||||
|
u16_t comlen;
|
||||||
|
/* encoding sequence length */
|
||||||
|
u16_t seqlen;
|
||||||
|
/* encoding varbinds sequence length */
|
||||||
|
u16_t vbseqlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds);
|
||||||
|
static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len);
|
||||||
|
static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream);
|
||||||
|
static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds);
|
||||||
|
|
||||||
|
/** Agent community string for sending traps */
|
||||||
|
extern const char *snmp_community_trap;
|
||||||
|
|
||||||
|
void* snmp_traps_handle;
|
||||||
|
|
||||||
|
struct snmp_trap_dst
|
||||||
|
{
|
||||||
|
/* destination IP address in network order */
|
||||||
|
ip_addr_t dip;
|
||||||
|
/* set to 0 when disabled, >0 when enabled */
|
||||||
|
u8_t enable;
|
||||||
|
};
|
||||||
|
static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];
|
||||||
|
|
||||||
|
static u8_t snmp_auth_traps_enabled = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Sets enable switch for this trap destination.
|
||||||
|
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
|
||||||
|
* @param enable switch if 0 destination is disabled >0 enabled.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
|
||||||
|
{
|
||||||
|
if (dst_idx < SNMP_TRAP_DESTINATIONS) {
|
||||||
|
trap_dst[dst_idx].enable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Sets IPv4 address for this trap destination.
|
||||||
|
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
|
||||||
|
* @param dst IPv4 address in host order.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst)
|
||||||
|
{
|
||||||
|
if (dst_idx < SNMP_TRAP_DESTINATIONS) {
|
||||||
|
ip_addr_set(&trap_dst[dst_idx].dip, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Enable/disable authentication traps
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_set_auth_traps_enabled(u8_t enable)
|
||||||
|
{
|
||||||
|
snmp_auth_traps_enabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Get authentication traps enabled state
|
||||||
|
*/
|
||||||
|
u8_t
|
||||||
|
snmp_get_auth_traps_enabled(void)
|
||||||
|
{
|
||||||
|
return snmp_auth_traps_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Sends a generic or enterprise specific trap message.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* is per RFC1215.
|
||||||
|
* Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps
|
||||||
|
* and .iso.org.dod.internet.private.enterprises.yourenterprise
|
||||||
|
* (sysObjectID) for specific traps.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
struct pbuf *p;
|
||||||
|
u16_t i, tot_len;
|
||||||
|
err_t err = ERR_OK;
|
||||||
|
|
||||||
|
trap_msg.snmp_version = 0;
|
||||||
|
|
||||||
|
for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) {
|
||||||
|
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 (eoid == NULL) {
|
||||||
|
trap_msg.enterprise = snmp_get_device_enterprise_oid();
|
||||||
|
} else {
|
||||||
|
trap_msg.enterprise = eoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
trap_msg.gen_trap = generic_trap;
|
||||||
|
if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) {
|
||||||
|
trap_msg.spc_trap = specific_trap;
|
||||||
|
} else {
|
||||||
|
trap_msg.spc_trap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts);
|
||||||
|
|
||||||
|
/* pass 0, calculate length fields */
|
||||||
|
tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds);
|
||||||
|
tot_len = snmp_trap_header_sum(&trap_msg, tot_len);
|
||||||
|
|
||||||
|
/* allocate pbuf(s) */
|
||||||
|
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM);
|
||||||
|
if (p != NULL) {
|
||||||
|
struct snmp_pbuf_stream pbuf_stream;
|
||||||
|
snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len);
|
||||||
|
|
||||||
|
/* pass 1, encode packet ino the pbuf(s) */
|
||||||
|
snmp_trap_header_enc(&trap_msg, &pbuf_stream);
|
||||||
|
snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds);
|
||||||
|
|
||||||
|
snmp_stats.outtraps++;
|
||||||
|
snmp_stats.outpkts++;
|
||||||
|
|
||||||
|
/** send to the TRAP destination */
|
||||||
|
snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT);
|
||||||
|
pbuf_free(p);
|
||||||
|
} else {
|
||||||
|
err = ERR_MEM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* routing error */
|
||||||
|
err = ERR_RTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Send generic SNMP trap
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_send_trap_generic(s32_t generic_trap)
|
||||||
|
{
|
||||||
|
static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } };
|
||||||
|
return snmp_send_trap(&oid, generic_trap, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Send specific SNMP trap with variable bindings
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds)
|
||||||
|
{
|
||||||
|
return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Send coldstart trap
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_coldstart_trap(void)
|
||||||
|
{
|
||||||
|
snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup snmp_traps
|
||||||
|
* Send authentication failure trap (used internally by agent)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmp_authfail_trap(void)
|
||||||
|
{
|
||||||
|
if (snmp_auth_traps_enabled != 0) {
|
||||||
|
snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16_t
|
||||||
|
snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds)
|
||||||
|
{
|
||||||
|
struct snmp_varbind *varbind;
|
||||||
|
u16_t tot_len;
|
||||||
|
u8_t tot_len_len;
|
||||||
|
|
||||||
|
tot_len = 0;
|
||||||
|
varbind = varbinds;
|
||||||
|
while (varbind != NULL) {
|
||||||
|
struct snmp_varbind_len len;
|
||||||
|
|
||||||
|
if (snmp_varbind_length(varbind, &len) == ERR_OK) {
|
||||||
|
tot_len += 1 + len.vb_len_len + len.vb_value_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
varbind = varbind->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
trap->vbseqlen = tot_len;
|
||||||
|
snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len);
|
||||||
|
tot_len += 1 + tot_len_len;
|
||||||
|
|
||||||
|
return tot_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @return the required length for encoding the trap header
|
||||||
|
*/
|
||||||
|
static u16_t
|
||||||
|
snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len)
|
||||||
|
{
|
||||||
|
u16_t tot_len;
|
||||||
|
u16_t len;
|
||||||
|
u8_t lenlen;
|
||||||
|
|
||||||
|
tot_len = vb_len;
|
||||||
|
|
||||||
|
snmp_asn1_enc_u32t_cnt(trap->ts, &len);
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len);
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len);
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
if (IP_IS_V6_VAL(trap->sip)) {
|
||||||
|
#if LWIP_IPV6
|
||||||
|
len = sizeof(ip_2_ip6(&trap->sip)->addr);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if LWIP_IPV4
|
||||||
|
len = sizeof(ip_2_ip4(&trap->sip)->addr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len);
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
trap->pdulen = tot_len;
|
||||||
|
snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen);
|
||||||
|
tot_len += 1 + lenlen;
|
||||||
|
|
||||||
|
trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF);
|
||||||
|
snmp_asn1_enc_length_cnt(trap->comlen, &lenlen);
|
||||||
|
tot_len += 1 + lenlen + trap->comlen;
|
||||||
|
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len);
|
||||||
|
snmp_asn1_enc_length_cnt(len, &lenlen);
|
||||||
|
tot_len += 1 + len + lenlen;
|
||||||
|
|
||||||
|
trap->seqlen = tot_len;
|
||||||
|
snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen);
|
||||||
|
tot_len += 1 + lenlen;
|
||||||
|
|
||||||
|
return tot_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds)
|
||||||
|
{
|
||||||
|
struct snmp_asn1_tlv tlv;
|
||||||
|
struct snmp_varbind *varbind;
|
||||||
|
|
||||||
|
varbind = varbinds;
|
||||||
|
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
|
||||||
|
while (varbind != NULL) {
|
||||||
|
snmp_append_outbound_varbind(pbuf_stream, varbind);
|
||||||
|
|
||||||
|
varbind = varbind->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes trap header from head to tail.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream)
|
||||||
|
{
|
||||||
|
struct snmp_asn1_tlv tlv;
|
||||||
|
|
||||||
|
/* 'Message' sequence */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version);
|
||||||
|
|
||||||
|
/* community */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen);
|
||||||
|
|
||||||
|
/* 'PDU' sequence */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
|
||||||
|
/* object ID */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0);
|
||||||
|
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len);
|
||||||
|
|
||||||
|
/* IP addr */
|
||||||
|
if (IP_IS_V6_VAL(trap->sip)) {
|
||||||
|
#if LWIP_IPV6
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr));
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if LWIP_IPV4
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr));
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trap length */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap);
|
||||||
|
|
||||||
|
/* specific trap */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap);
|
||||||
|
|
||||||
|
/* timestamp */
|
||||||
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0);
|
||||||
|
snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len);
|
||||||
|
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
|
||||||
|
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP */
|
||||||
136
ext/lwip/src/apps/snmp/snmpv3.c
Executable file
136
ext/lwip/src/apps/snmp/snmpv3.c
Executable file
@@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Additional SNMPv3 functionality RFC3414 and RFC3826.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Elias Oenal.
|
||||||
|
* 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: Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "snmpv3_priv.h"
|
||||||
|
#include "lwip/apps/snmpv3.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && LWIP_SNMP_V3
|
||||||
|
|
||||||
|
#ifdef LWIP_SNMPV3_INCLUDE_ENGINE
|
||||||
|
#include LWIP_SNMPV3_INCLUDE_ENGINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SNMP_MAX_TIME_BOOT 2147483647UL
|
||||||
|
|
||||||
|
/** Call this if engine has been changed. Has to reset boots, see below */
|
||||||
|
void
|
||||||
|
snmpv3_engine_id_changed(void)
|
||||||
|
{
|
||||||
|
snmpv3_set_engine_boots(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** According to RFC3414 2.2.2.
|
||||||
|
*
|
||||||
|
* The number of times that the SNMP engine has
|
||||||
|
* (re-)initialized itself since snmpEngineID
|
||||||
|
* was last configured.
|
||||||
|
*/
|
||||||
|
u32_t
|
||||||
|
snmpv3_get_engine_boots_internal(void)
|
||||||
|
{
|
||||||
|
if (snmpv3_get_engine_boots() == 0 ||
|
||||||
|
snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) {
|
||||||
|
return snmpv3_get_engine_boots();
|
||||||
|
}
|
||||||
|
|
||||||
|
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
|
||||||
|
return snmpv3_get_engine_boots();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RFC3414 2.2.2.
|
||||||
|
*
|
||||||
|
* Once the timer reaches 2147483647 it gets reset to zero and the
|
||||||
|
* engine boot ups get incremented.
|
||||||
|
*/
|
||||||
|
u32_t
|
||||||
|
snmpv3_get_engine_time_internal(void)
|
||||||
|
{
|
||||||
|
if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) {
|
||||||
|
snmpv3_reset_engine_time();
|
||||||
|
|
||||||
|
if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) {
|
||||||
|
snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1);
|
||||||
|
} else {
|
||||||
|
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return snmpv3_get_engine_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_SNMP_V3_CRYPTO
|
||||||
|
|
||||||
|
/* This function ignores the byte order suggestion in RFC3414
|
||||||
|
* since it simply doesn't influence the effectiveness of an IV.
|
||||||
|
*
|
||||||
|
* Implementing RFC3826 priv param algorithm if LWIP_RAND is available.
|
||||||
|
*
|
||||||
|
* @todo: This is a potential thread safety issue.
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmpv3_build_priv_param(u8_t* priv_param)
|
||||||
|
{
|
||||||
|
#ifdef LWIP_RAND /* Based on RFC3826 */
|
||||||
|
static u8_t init;
|
||||||
|
static u32_t priv1, priv2;
|
||||||
|
|
||||||
|
/* Lazy initialisation */
|
||||||
|
if (init == 0) {
|
||||||
|
init = 1;
|
||||||
|
priv1 = LWIP_RAND();
|
||||||
|
priv2 = LWIP_RAND();
|
||||||
|
}
|
||||||
|
|
||||||
|
SMEMCPY(&priv_param[0], &priv1, sizeof(priv1));
|
||||||
|
SMEMCPY(&priv_param[4], &priv2, sizeof(priv2));
|
||||||
|
|
||||||
|
/* Emulate 64bit increment */
|
||||||
|
priv1++;
|
||||||
|
if (!priv1) { /* Overflow */
|
||||||
|
priv2++;
|
||||||
|
}
|
||||||
|
#else /* Based on RFC3414 */
|
||||||
|
static u32_t ctr;
|
||||||
|
u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS();
|
||||||
|
SMEMCPY(&priv_param[0], &boots, 4);
|
||||||
|
SMEMCPY(&priv_param[4], &ctr, 4);
|
||||||
|
ctr++;
|
||||||
|
#endif
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_SNMP_V3_CRYPTO */
|
||||||
|
|
||||||
|
#endif
|
||||||
145
ext/lwip/src/apps/snmp/snmpv3_dummy.c
Executable file
145
ext/lwip/src/apps/snmp/snmpv3_dummy.c
Executable file
@@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Dummy SNMPv3 functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Elias Oenal.
|
||||||
|
* 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: Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
* Dirk Ziegelmeier <dirk@ziegelmeier.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmpv3.h"
|
||||||
|
#include "snmpv3_priv.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && LWIP_SNMP_V3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username is a pointer to a string.
|
||||||
|
* @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found.
|
||||||
|
* @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
|
||||||
|
* @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found.
|
||||||
|
* @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key)
|
||||||
|
{
|
||||||
|
const char* engine_id;
|
||||||
|
u8_t engine_id_len;
|
||||||
|
|
||||||
|
if(strlen(username) == 0) {
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memcmp(username, "lwip", 4) != 0) {
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmpv3_get_engine_id(&engine_id, &engine_id_len);
|
||||||
|
|
||||||
|
if(auth_key != NULL) {
|
||||||
|
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10,
|
||||||
|
(const u8_t*)engine_id, engine_id_len,
|
||||||
|
auth_key);
|
||||||
|
*auth_algo = SNMP_V3_AUTH_ALGO_SHA;
|
||||||
|
}
|
||||||
|
if(priv_key != NULL) {
|
||||||
|
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10,
|
||||||
|
(const u8_t*)engine_id, engine_id_len,
|
||||||
|
priv_key);
|
||||||
|
*priv_algo = SNMP_V3_PRIV_ALGO_DES;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get engine ID from persistence
|
||||||
|
* @param id
|
||||||
|
* @param len
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmpv3_get_engine_id(const char **id, u8_t *len)
|
||||||
|
{
|
||||||
|
*id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02";
|
||||||
|
*len = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store engine ID in persistence
|
||||||
|
* @param id
|
||||||
|
* @param len
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
snmpv3_set_engine_id(const char *id, u8_t len)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(id);
|
||||||
|
LWIP_UNUSED_ARG(len);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get engine boots from persistence. Must be increased on each boot.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
u32_t
|
||||||
|
snmpv3_get_engine_boots(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store engine boots in persistence
|
||||||
|
* @param boots
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmpv3_set_engine_boots(u32_t boots)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(boots);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC3414 2.2.2.
|
||||||
|
* Once the timer reaches 2147483647 it gets reset to zero and the
|
||||||
|
* engine boot ups get incremented.
|
||||||
|
*/
|
||||||
|
u32_t
|
||||||
|
snmpv3_get_engine_time(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset current engine time to 0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
snmpv3_reset_engine_time(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && LWIP_SNMP_V3 */
|
||||||
331
ext/lwip/src/apps/snmp/snmpv3_mbedtls.c
Executable file
331
ext/lwip/src/apps/snmp/snmpv3_mbedtls.c
Executable file
@@ -0,0 +1,331 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNMPv3 crypto/auth functions implemented for ARM mbedtls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier.
|
||||||
|
* 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: Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
* Dirk Ziegelmeier <dirk@ziegelmeier.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/snmpv3.h"
|
||||||
|
#include "snmpv3_priv.h"
|
||||||
|
#include "lwip/arch.h"
|
||||||
|
#include "snmp_msg.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS
|
||||||
|
|
||||||
|
#include "mbedtls/md.h"
|
||||||
|
#include "mbedtls/cipher.h"
|
||||||
|
|
||||||
|
#include "mbedtls/md5.h"
|
||||||
|
#include "mbedtls/sha1.h"
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length,
|
||||||
|
const u8_t* key, u8_t algo, u8_t* hmac_out)
|
||||||
|
{
|
||||||
|
u32_t i;
|
||||||
|
u8_t key_len;
|
||||||
|
const mbedtls_md_info_t *md_info;
|
||||||
|
mbedtls_md_context_t ctx;
|
||||||
|
struct snmp_pbuf_stream read_stream;
|
||||||
|
snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length);
|
||||||
|
|
||||||
|
if (algo == SNMP_V3_AUTH_ALGO_MD5) {
|
||||||
|
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
|
||||||
|
key_len = SNMP_V3_MD5_LEN;
|
||||||
|
} else if (algo == SNMP_V3_AUTH_ALGO_SHA) {
|
||||||
|
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||||
|
key_len = SNMP_V3_SHA_LEN;
|
||||||
|
} else {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_md_init(&ctx);
|
||||||
|
if(mbedtls_md_setup(&ctx, md_info, 1) != 0) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) {
|
||||||
|
goto free_md;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
u8_t byte;
|
||||||
|
|
||||||
|
if (snmp_pbuf_stream_read(&read_stream, &byte)) {
|
||||||
|
goto free_md;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) {
|
||||||
|
goto free_md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) {
|
||||||
|
goto free_md;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_md_free(&ctx);
|
||||||
|
return ERR_OK;
|
||||||
|
|
||||||
|
free_md:
|
||||||
|
mbedtls_md_free(&ctx);
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_SNMP_V3_CRYPTO
|
||||||
|
|
||||||
|
err_t
|
||||||
|
snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length,
|
||||||
|
const u8_t* key, const u8_t* priv_param, const u32_t engine_boots,
|
||||||
|
const u32_t engine_time, u8_t algo, u8_t mode)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
mbedtls_cipher_context_t ctx;
|
||||||
|
const mbedtls_cipher_info_t *cipher_info;
|
||||||
|
|
||||||
|
struct snmp_pbuf_stream read_stream;
|
||||||
|
struct snmp_pbuf_stream write_stream;
|
||||||
|
snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length);
|
||||||
|
snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length);
|
||||||
|
mbedtls_cipher_init(&ctx);
|
||||||
|
|
||||||
|
if (algo == SNMP_V3_PRIV_ALGO_DES) {
|
||||||
|
u8_t iv_local[8];
|
||||||
|
u8_t out_bytes[8];
|
||||||
|
size_t out_len;
|
||||||
|
|
||||||
|
/* RFC 3414 mandates padding for DES */
|
||||||
|
if ((length & 0x07) != 0) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC);
|
||||||
|
if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare IV */
|
||||||
|
for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) {
|
||||||
|
iv_local[i] = priv_param[i] ^ key[i + 8];
|
||||||
|
}
|
||||||
|
if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += 8) {
|
||||||
|
size_t j;
|
||||||
|
u8_t in_bytes[8];
|
||||||
|
out_len = LWIP_ARRAYSIZE(out_bytes) ;
|
||||||
|
|
||||||
|
for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) {
|
||||||
|
snmp_pbuf_stream_read(&read_stream, &in_bytes[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_len = LWIP_ARRAYSIZE(out_bytes);
|
||||||
|
if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len);
|
||||||
|
} else if (algo == SNMP_V3_PRIV_ALGO_AES) {
|
||||||
|
u8_t iv_local[16];
|
||||||
|
|
||||||
|
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128);
|
||||||
|
if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IV is the big endian concatenation of boots,
|
||||||
|
* uptime and priv param - see RFC3826.
|
||||||
|
*/
|
||||||
|
iv_local[0 + 0] = (engine_boots >> 24) & 0xFF;
|
||||||
|
iv_local[0 + 1] = (engine_boots >> 16) & 0xFF;
|
||||||
|
iv_local[0 + 2] = (engine_boots >> 8) & 0xFF;
|
||||||
|
iv_local[0 + 3] = (engine_boots >> 0) & 0xFF;
|
||||||
|
iv_local[4 + 0] = (engine_time >> 24) & 0xFF;
|
||||||
|
iv_local[4 + 1] = (engine_time >> 16) & 0xFF;
|
||||||
|
iv_local[4 + 2] = (engine_time >> 8) & 0xFF;
|
||||||
|
iv_local[4 + 3] = (engine_time >> 0) & 0xFF;
|
||||||
|
SMEMCPY(iv_local + 8, priv_param, 8);
|
||||||
|
if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
u8_t in_byte;
|
||||||
|
u8_t out_byte;
|
||||||
|
size_t out_len = sizeof(out_byte);
|
||||||
|
|
||||||
|
snmp_pbuf_stream_read(&read_stream, &in_byte);
|
||||||
|
if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
snmp_pbuf_stream_write(&write_stream, out_byte);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_cipher_free(&ctx);
|
||||||
|
return ERR_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
mbedtls_cipher_free(&ctx);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP_V3_CRYPTO */
|
||||||
|
|
||||||
|
/* A.2.1. Password to Key Sample Code for MD5 */
|
||||||
|
void
|
||||||
|
snmpv3_password_to_key_md5(
|
||||||
|
const u8_t *password, /* IN */
|
||||||
|
u8_t passwordlen, /* IN */
|
||||||
|
const u8_t *engineID, /* IN - pointer to snmpEngineID */
|
||||||
|
u8_t engineLength,/* IN - length of snmpEngineID */
|
||||||
|
u8_t *key) /* OUT - pointer to caller 16-octet buffer */
|
||||||
|
{
|
||||||
|
mbedtls_md5_context MD;
|
||||||
|
u8_t *cp, password_buf[64];
|
||||||
|
u32_t password_index = 0;
|
||||||
|
u8_t i;
|
||||||
|
u32_t count = 0;
|
||||||
|
|
||||||
|
mbedtls_md5_init(&MD); /* initialize MD5 */
|
||||||
|
mbedtls_md5_starts(&MD);
|
||||||
|
|
||||||
|
/**********************************************/
|
||||||
|
/* Use while loop until we've done 1 Megabyte */
|
||||||
|
/**********************************************/
|
||||||
|
while (count < 1048576) {
|
||||||
|
cp = password_buf;
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
/*************************************************/
|
||||||
|
/* Take the next octet of the password, wrapping */
|
||||||
|
/* to the beginning of the password as necessary.*/
|
||||||
|
/*************************************************/
|
||||||
|
*cp++ = password[password_index++ % passwordlen];
|
||||||
|
}
|
||||||
|
mbedtls_md5_update(&MD, password_buf, 64);
|
||||||
|
count += 64;
|
||||||
|
}
|
||||||
|
mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Now localize the key with the engineID and pass */
|
||||||
|
/* through MD5 to produce final key */
|
||||||
|
/* May want to ensure that engineLength <= 32, */
|
||||||
|
/* otherwise need to use a buffer larger than 64 */
|
||||||
|
/*****************************************************/
|
||||||
|
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);
|
||||||
|
mbedtls_md5_finish(&MD, key);
|
||||||
|
|
||||||
|
mbedtls_md5_free(&MD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A.2.2. Password to Key Sample Code for SHA */
|
||||||
|
void
|
||||||
|
snmpv3_password_to_key_sha(
|
||||||
|
const u8_t *password, /* IN */
|
||||||
|
u8_t passwordlen, /* IN */
|
||||||
|
const u8_t *engineID, /* IN - pointer to snmpEngineID */
|
||||||
|
u8_t engineLength,/* IN - length of snmpEngineID */
|
||||||
|
u8_t *key) /* OUT - pointer to caller 20-octet buffer */
|
||||||
|
{
|
||||||
|
mbedtls_sha1_context SH;
|
||||||
|
u8_t *cp, password_buf[72];
|
||||||
|
u32_t password_index = 0;
|
||||||
|
u8_t i;
|
||||||
|
u32_t count = 0;
|
||||||
|
|
||||||
|
mbedtls_sha1_init(&SH); /* initialize SHA */
|
||||||
|
mbedtls_sha1_starts(&SH);
|
||||||
|
|
||||||
|
/**********************************************/
|
||||||
|
/* Use while loop until we've done 1 Megabyte */
|
||||||
|
/**********************************************/
|
||||||
|
while (count < 1048576) {
|
||||||
|
cp = password_buf;
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
/*************************************************/
|
||||||
|
/* Take the next octet of the password, wrapping */
|
||||||
|
/* to the beginning of the password as necessary.*/
|
||||||
|
/*************************************************/
|
||||||
|
*cp++ = password[password_index++ % passwordlen];
|
||||||
|
}
|
||||||
|
mbedtls_sha1_update(&SH, password_buf, 64);
|
||||||
|
count += 64;
|
||||||
|
}
|
||||||
|
mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Now localize the key with the engineID and pass */
|
||||||
|
/* through SHA to produce final key */
|
||||||
|
/* May want to ensure that engineLength <= 32, */
|
||||||
|
/* otherwise need to use a buffer larger than 72 */
|
||||||
|
/*****************************************************/
|
||||||
|
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);
|
||||||
|
mbedtls_sha1_finish(&SH, key);
|
||||||
|
|
||||||
|
mbedtls_sha1_free(&SH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */
|
||||||
66
ext/lwip/src/apps/snmp/snmpv3_priv.h
Executable file
66
ext/lwip/src/apps/snmp/snmpv3_priv.h
Executable file
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Elias Oenal.
|
||||||
|
* 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: Elias Oenal <lwip@eliasoenal.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H
|
||||||
|
#define LWIP_HDR_APPS_SNMP_V3_PRIV_H
|
||||||
|
|
||||||
|
#include "lwip/apps/snmp_opts.h"
|
||||||
|
|
||||||
|
#if LWIP_SNMP && LWIP_SNMP_V3
|
||||||
|
|
||||||
|
#include "snmp_pbuf_stream.h"
|
||||||
|
|
||||||
|
/* According to RFC 3411 */
|
||||||
|
#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32
|
||||||
|
#define SNMP_V3_MAX_USER_LENGTH 32
|
||||||
|
|
||||||
|
#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12
|
||||||
|
#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8
|
||||||
|
|
||||||
|
#define SNMP_V3_AUTH_FLAG 0x01
|
||||||
|
#define SNMP_V3_PRIV_FLAG 0x02
|
||||||
|
|
||||||
|
#define SNMP_V3_MD5_LEN 16
|
||||||
|
#define SNMP_V3_SHA_LEN 20
|
||||||
|
|
||||||
|
u32_t snmpv3_get_engine_boots_internal(void);
|
||||||
|
u32_t snmpv3_get_engine_time_internal(void);
|
||||||
|
err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out);
|
||||||
|
err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key,
|
||||||
|
const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode);
|
||||||
|
err_t snmpv3_build_priv_param(u8_t* priv_param);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */
|
||||||
727
ext/lwip/src/apps/sntp/sntp.c
Executable file
727
ext/lwip/src/apps/sntp/sntp.c
Executable file
@@ -0,0 +1,727 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* SNTP client module
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Frédéric Bernon, Simon Goldschmidt
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup sntp SNTP
|
||||||
|
* @ingroup apps
|
||||||
|
*
|
||||||
|
* This is simple "SNTP" client for the lwIP raw API.
|
||||||
|
* It is a minimal implementation of SNTPv4 as specified in RFC 4330.
|
||||||
|
*
|
||||||
|
* For a list of some public NTP servers, see this link :
|
||||||
|
* http://support.ntp.org/bin/view/Servers/NTPPoolServers
|
||||||
|
*
|
||||||
|
* @todo:
|
||||||
|
* - set/change servers at runtime
|
||||||
|
* - complete SNTP_CHECK_RESPONSE checks 3 and 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/apps/sntp.h"
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/timeouts.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/dns.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/dhcp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if LWIP_UDP
|
||||||
|
|
||||||
|
/* Handle support for more than one server via SNTP_MAX_SERVERS */
|
||||||
|
#if SNTP_MAX_SERVERS > 1
|
||||||
|
#define SNTP_SUPPORT_MULTIPLE_SERVERS 1
|
||||||
|
#else /* NTP_MAX_SERVERS > 1 */
|
||||||
|
#define SNTP_SUPPORT_MULTIPLE_SERVERS 0
|
||||||
|
#endif /* NTP_MAX_SERVERS > 1 */
|
||||||
|
|
||||||
|
#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK)
|
||||||
|
#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Configure behaviour depending on microsecond or second precision */
|
||||||
|
#ifdef SNTP_SET_SYSTEM_TIME_US
|
||||||
|
#define SNTP_CALC_TIME_US 1
|
||||||
|
#define SNTP_RECEIVE_TIME_SIZE 2
|
||||||
|
#else
|
||||||
|
#define SNTP_SET_SYSTEM_TIME_US(sec, us)
|
||||||
|
#define SNTP_CALC_TIME_US 0
|
||||||
|
#define SNTP_RECEIVE_TIME_SIZE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* the various debug levels for this file */
|
||||||
|
#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE)
|
||||||
|
#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE)
|
||||||
|
#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
|
||||||
|
#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
|
||||||
|
#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
|
||||||
|
|
||||||
|
#define SNTP_ERR_KOD 1
|
||||||
|
|
||||||
|
/* SNTP protocol defines */
|
||||||
|
#define SNTP_MSG_LEN 48
|
||||||
|
|
||||||
|
#define SNTP_OFFSET_LI_VN_MODE 0
|
||||||
|
#define SNTP_LI_MASK 0xC0
|
||||||
|
#define SNTP_LI_NO_WARNING 0x00
|
||||||
|
#define SNTP_LI_LAST_MINUTE_61_SEC 0x01
|
||||||
|
#define SNTP_LI_LAST_MINUTE_59_SEC 0x02
|
||||||
|
#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */
|
||||||
|
|
||||||
|
#define SNTP_VERSION_MASK 0x38
|
||||||
|
#define SNTP_VERSION (4/* NTP Version 4*/<<3)
|
||||||
|
|
||||||
|
#define SNTP_MODE_MASK 0x07
|
||||||
|
#define SNTP_MODE_CLIENT 0x03
|
||||||
|
#define SNTP_MODE_SERVER 0x04
|
||||||
|
#define SNTP_MODE_BROADCAST 0x05
|
||||||
|
|
||||||
|
#define SNTP_OFFSET_STRATUM 1
|
||||||
|
#define SNTP_STRATUM_KOD 0x00
|
||||||
|
|
||||||
|
#define SNTP_OFFSET_ORIGINATE_TIME 24
|
||||||
|
#define SNTP_OFFSET_RECEIVE_TIME 32
|
||||||
|
#define SNTP_OFFSET_TRANSMIT_TIME 40
|
||||||
|
|
||||||
|
/* number of seconds between 1900 and 1970 (MSB=1)*/
|
||||||
|
#define DIFF_SEC_1900_1970 (2208988800UL)
|
||||||
|
/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */
|
||||||
|
#define DIFF_SEC_1970_2036 (2085978496UL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SNTP packet format (without optional fields)
|
||||||
|
* Timestamps are coded as 64 bits:
|
||||||
|
* - 32 bits seconds since Jan 01, 1970, 00:00
|
||||||
|
* - 32 bits seconds fraction (0-padded)
|
||||||
|
* For future use, if the MSB in the seconds part is set, seconds are based
|
||||||
|
* on Feb 07, 2036, 06:28:16.
|
||||||
|
*/
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct sntp_msg {
|
||||||
|
PACK_STRUCT_FLD_8(u8_t li_vn_mode);
|
||||||
|
PACK_STRUCT_FLD_8(u8_t stratum);
|
||||||
|
PACK_STRUCT_FLD_8(u8_t poll);
|
||||||
|
PACK_STRUCT_FLD_8(u8_t precision);
|
||||||
|
PACK_STRUCT_FIELD(u32_t root_delay);
|
||||||
|
PACK_STRUCT_FIELD(u32_t root_dispersion);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reference_identifier);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reference_timestamp[2]);
|
||||||
|
PACK_STRUCT_FIELD(u32_t originate_timestamp[2]);
|
||||||
|
PACK_STRUCT_FIELD(u32_t receive_timestamp[2]);
|
||||||
|
PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* function prototypes */
|
||||||
|
static void sntp_request(void *arg);
|
||||||
|
|
||||||
|
/** The operating mode */
|
||||||
|
static u8_t sntp_opmode;
|
||||||
|
|
||||||
|
/** The UDP pcb used by the SNTP client */
|
||||||
|
static struct udp_pcb* sntp_pcb;
|
||||||
|
/** Names/Addresses of servers */
|
||||||
|
struct sntp_server {
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
char* name;
|
||||||
|
#endif /* SNTP_SERVER_DNS */
|
||||||
|
ip_addr_t addr;
|
||||||
|
};
|
||||||
|
static struct sntp_server sntp_servers[SNTP_MAX_SERVERS];
|
||||||
|
|
||||||
|
#if SNTP_GET_SERVERS_FROM_DHCP
|
||||||
|
static u8_t sntp_set_servers_from_dhcp;
|
||||||
|
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
|
||||||
|
#if SNTP_SUPPORT_MULTIPLE_SERVERS
|
||||||
|
/** The currently used server (initialized to 0) */
|
||||||
|
static u8_t sntp_current_server;
|
||||||
|
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
||||||
|
#define sntp_current_server 0
|
||||||
|
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
||||||
|
|
||||||
|
#if SNTP_RETRY_TIMEOUT_EXP
|
||||||
|
#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
|
||||||
|
/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */
|
||||||
|
static u32_t sntp_retry_timeout;
|
||||||
|
#else /* SNTP_RETRY_TIMEOUT_EXP */
|
||||||
|
#define SNTP_RESET_RETRY_TIMEOUT()
|
||||||
|
#define sntp_retry_timeout SNTP_RETRY_TIMEOUT
|
||||||
|
#endif /* SNTP_RETRY_TIMEOUT_EXP */
|
||||||
|
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 1
|
||||||
|
/** Saves the last server address to compare with response */
|
||||||
|
static ip_addr_t sntp_last_server_address;
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
||||||
|
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 2
|
||||||
|
/** Saves the last timestamp sent (which is sent back by the server)
|
||||||
|
* to compare against in response */
|
||||||
|
static u32_t sntp_last_timestamp_sent[2];
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SNTP processing of received timestamp
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_process(u32_t *receive_timestamp)
|
||||||
|
{
|
||||||
|
/* convert SNTP time (1900-based) to unix GMT time (1970-based)
|
||||||
|
* if MSB is 0, SNTP time is 2036-based!
|
||||||
|
*/
|
||||||
|
u32_t rx_secs = 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 = 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));
|
||||||
|
|
||||||
|
#else /* SNTP_CALC_TIME_US */
|
||||||
|
|
||||||
|
/* change system time and/or the update the RTC clock */
|
||||||
|
SNTP_SET_SYSTEM_TIME(t);
|
||||||
|
/* display local time from GMT time */
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim)));
|
||||||
|
#endif /* SNTP_CALC_TIME_US */
|
||||||
|
LWIP_UNUSED_ARG(tim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize request struct to be sent to server.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_initialize_request(struct sntp_msg *req)
|
||||||
|
{
|
||||||
|
memset(req, 0, SNTP_MSG_LEN);
|
||||||
|
req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
|
||||||
|
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 2
|
||||||
|
{
|
||||||
|
u32_t sntp_time_sec, sntp_time_us;
|
||||||
|
/* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
|
||||||
|
SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
|
||||||
|
sntp_last_timestamp_sent[0] = 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] = lwip_htonl(sntp_time_us);
|
||||||
|
req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
|
||||||
|
}
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retry: send a new request (and increase retry timeout).
|
||||||
|
*
|
||||||
|
* @param arg is unused (only necessary to conform to sys_timeout)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_retry(void* arg)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
|
||||||
|
sntp_retry_timeout));
|
||||||
|
|
||||||
|
/* set up a timer to send a retry and increase the retry delay */
|
||||||
|
sys_timeout(sntp_retry_timeout, sntp_request, NULL);
|
||||||
|
|
||||||
|
#if SNTP_RETRY_TIMEOUT_EXP
|
||||||
|
{
|
||||||
|
u32_t new_retry_timeout;
|
||||||
|
/* increase the timeout for next retry */
|
||||||
|
new_retry_timeout = sntp_retry_timeout << 1;
|
||||||
|
/* limit to maximum timeout and prevent overflow */
|
||||||
|
if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
|
||||||
|
(new_retry_timeout > sntp_retry_timeout)) {
|
||||||
|
sntp_retry_timeout = new_retry_timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SNTP_RETRY_TIMEOUT_EXP */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SNTP_SUPPORT_MULTIPLE_SERVERS
|
||||||
|
/**
|
||||||
|
* If Kiss-of-Death is received (or another packet parsing error),
|
||||||
|
* try the next server or retry the current server and increase the retry
|
||||||
|
* timeout if only one server is available.
|
||||||
|
* (implicitly, SNTP_MAX_SERVERS > 1)
|
||||||
|
*
|
||||||
|
* @param arg is unused (only necessary to conform to sys_timeout)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_try_next_server(void* arg)
|
||||||
|
{
|
||||||
|
u8_t old_server, i;
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
old_server = sntp_current_server;
|
||||||
|
for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) {
|
||||||
|
sntp_current_server++;
|
||||||
|
if (sntp_current_server >= SNTP_MAX_SERVERS) {
|
||||||
|
sntp_current_server = 0;
|
||||||
|
}
|
||||||
|
if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr)
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
|| (sntp_servers[sntp_current_server].name != NULL)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
|
||||||
|
(u16_t)sntp_current_server));
|
||||||
|
/* new server: reset retry timeout */
|
||||||
|
SNTP_RESET_RETRY_TIMEOUT();
|
||||||
|
/* instantly send a request to the next server */
|
||||||
|
sntp_request(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* no other valid server found */
|
||||||
|
sntp_current_server = old_server;
|
||||||
|
sntp_retry(NULL);
|
||||||
|
}
|
||||||
|
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
||||||
|
/* Always retry on error if only one server is supported */
|
||||||
|
#define sntp_try_next_server sntp_retry
|
||||||
|
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
|
||||||
|
|
||||||
|
/** UDP recv callback for the sntp pcb */
|
||||||
|
static void
|
||||||
|
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||||
|
{
|
||||||
|
u8_t mode;
|
||||||
|
u8_t stratum;
|
||||||
|
u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
LWIP_UNUSED_ARG(pcb);
|
||||||
|
|
||||||
|
/* packet received: stop retry timeout */
|
||||||
|
sys_untimeout(sntp_try_next_server, NULL);
|
||||||
|
sys_untimeout(sntp_request, NULL);
|
||||||
|
|
||||||
|
err = ERR_ARG;
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 1
|
||||||
|
/* check server address and port */
|
||||||
|
if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) &&
|
||||||
|
(port == SNTP_PORT))
|
||||||
|
#else /* SNTP_CHECK_RESPONSE >= 1 */
|
||||||
|
LWIP_UNUSED_ARG(addr);
|
||||||
|
LWIP_UNUSED_ARG(port);
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
||||||
|
{
|
||||||
|
/* process the response */
|
||||||
|
if (p->tot_len == SNTP_MSG_LEN) {
|
||||||
|
pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
|
||||||
|
mode &= SNTP_MODE_MASK;
|
||||||
|
/* if this is a SNTP response... */
|
||||||
|
if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) ||
|
||||||
|
((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) {
|
||||||
|
pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
|
||||||
|
if (stratum == SNTP_STRATUM_KOD) {
|
||||||
|
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
|
||||||
|
err = SNTP_ERR_KOD;
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
|
||||||
|
} else {
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 2
|
||||||
|
/* check originate_timetamp against sntp_last_timestamp_sent */
|
||||||
|
u32_t originate_timestamp[2];
|
||||||
|
pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
|
||||||
|
if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
|
||||||
|
(originate_timestamp[1] != sntp_last_timestamp_sent[1]))
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
|
||||||
|
} else
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 2 */
|
||||||
|
/* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
|
||||||
|
{
|
||||||
|
/* correct answer */
|
||||||
|
err = ERR_OK;
|
||||||
|
pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
|
||||||
|
/* wait for correct response */
|
||||||
|
err = ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 1
|
||||||
|
else {
|
||||||
|
/* packet from wrong remote address or port, wait for correct response */
|
||||||
|
err = ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
||||||
|
pbuf_free(p);
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
sntp_process(receive_timestamp);
|
||||||
|
|
||||||
|
/* Set up timeout for next request (only if poll response was received)*/
|
||||||
|
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
||||||
|
/* Correct response, reset retry timeout */
|
||||||
|
SNTP_RESET_RETRY_TIMEOUT();
|
||||||
|
|
||||||
|
sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
|
||||||
|
(u32_t)SNTP_UPDATE_DELAY));
|
||||||
|
}
|
||||||
|
} else if (err != ERR_TIMEOUT) {
|
||||||
|
/* Errors are only processed in case of an explicit poll response */
|
||||||
|
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
||||||
|
if (err == SNTP_ERR_KOD) {
|
||||||
|
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
|
||||||
|
sntp_try_next_server(NULL);
|
||||||
|
} else {
|
||||||
|
/* another error, try the same server again */
|
||||||
|
sntp_retry(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually send an sntp request to a server.
|
||||||
|
*
|
||||||
|
* @param server_addr resolved IP address of the SNTP server
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_send_request(const ip_addr_t *server_addr)
|
||||||
|
{
|
||||||
|
struct pbuf* p;
|
||||||
|
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
|
||||||
|
if (p != NULL) {
|
||||||
|
struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
|
||||||
|
/* initialize request message */
|
||||||
|
sntp_initialize_request(sntpmsg);
|
||||||
|
/* send request */
|
||||||
|
udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
|
||||||
|
/* free the pbuf after sending it */
|
||||||
|
pbuf_free(p);
|
||||||
|
/* set up receive timeout: try next server or retry on timeout */
|
||||||
|
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
|
||||||
|
#if SNTP_CHECK_RESPONSE >= 1
|
||||||
|
/* save server address to verify it in sntp_recv */
|
||||||
|
ip_addr_set(&sntp_last_server_address, server_addr);
|
||||||
|
#endif /* SNTP_CHECK_RESPONSE >= 1 */
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
|
||||||
|
(u32_t)SNTP_RETRY_TIMEOUT));
|
||||||
|
/* out of memory: set up a timer to send a retry */
|
||||||
|
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
/**
|
||||||
|
* DNS found callback when using DNS names as server address.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(hostname);
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
if (ipaddr != NULL) {
|
||||||
|
/* Address resolved, send request */
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
|
||||||
|
sntp_send_request(ipaddr);
|
||||||
|
} else {
|
||||||
|
/* DNS resolving failed -> try another server */
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
|
||||||
|
sntp_try_next_server(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SNTP_SERVER_DNS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send out an sntp request.
|
||||||
|
*
|
||||||
|
* @param arg is unused (only necessary to conform to sys_timeout)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sntp_request(void *arg)
|
||||||
|
{
|
||||||
|
ip_addr_t sntp_server_address;
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
/* initialize SNTP server address */
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
if (sntp_servers[sntp_current_server].name) {
|
||||||
|
/* always resolve the name and rely on dns-internal caching & timeout */
|
||||||
|
ip_addr_set_zero(&sntp_servers[sntp_current_server].addr);
|
||||||
|
err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address,
|
||||||
|
sntp_dns_found, NULL);
|
||||||
|
if (err == ERR_INPROGRESS) {
|
||||||
|
/* DNS request sent, wait for sntp_dns_found being called */
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
|
||||||
|
return;
|
||||||
|
} else if (err == ERR_OK) {
|
||||||
|
sntp_servers[sntp_current_server].addr = sntp_server_address;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif /* SNTP_SERVER_DNS */
|
||||||
|
{
|
||||||
|
sntp_server_address = sntp_servers[sntp_current_server].addr;
|
||||||
|
err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n",
|
||||||
|
ipaddr_ntoa(&sntp_server_address)));
|
||||||
|
sntp_send_request(&sntp_server_address);
|
||||||
|
} else {
|
||||||
|
/* address conversion failed, try another server */
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
|
||||||
|
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Initialize this module.
|
||||||
|
* Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sntp_init(void)
|
||||||
|
{
|
||||||
|
#ifdef SNTP_SERVER_ADDRESS
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
sntp_setservername(0, SNTP_SERVER_ADDRESS);
|
||||||
|
#else
|
||||||
|
#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0
|
||||||
|
#endif
|
||||||
|
#endif /* SNTP_SERVER_ADDRESS */
|
||||||
|
|
||||||
|
if (sntp_pcb == NULL) {
|
||||||
|
sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||||
|
LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
|
||||||
|
if (sntp_pcb != NULL) {
|
||||||
|
udp_recv(sntp_pcb, sntp_recv, NULL);
|
||||||
|
|
||||||
|
if (sntp_opmode == SNTP_OPMODE_POLL) {
|
||||||
|
SNTP_RESET_RETRY_TIMEOUT();
|
||||||
|
#if SNTP_STARTUP_DELAY
|
||||||
|
sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL);
|
||||||
|
#else
|
||||||
|
sntp_request(NULL);
|
||||||
|
#endif
|
||||||
|
} else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) {
|
||||||
|
ip_set_option(sntp_pcb, SOF_BROADCAST);
|
||||||
|
udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Stop this module.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Get enabled state.
|
||||||
|
*/
|
||||||
|
u8_t sntp_enabled(void)
|
||||||
|
{
|
||||||
|
return (sntp_pcb != NULL)? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Sets the operating mode.
|
||||||
|
* @param operating_mode one of the available operating modes
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sntp_setoperatingmode(u8_t operating_mode)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY);
|
||||||
|
LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL);
|
||||||
|
sntp_opmode = operating_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Gets the operating mode.
|
||||||
|
*/
|
||||||
|
u8_t
|
||||||
|
sntp_getoperatingmode(void)
|
||||||
|
{
|
||||||
|
return sntp_opmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SNTP_GET_SERVERS_FROM_DHCP
|
||||||
|
/**
|
||||||
|
* Config SNTP server handling by IP address, name, or DHCP; clear table
|
||||||
|
* @param set_servers_from_dhcp enable or disable getting server addresses from dhcp
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sntp_servermode_dhcp(int set_servers_from_dhcp)
|
||||||
|
{
|
||||||
|
u8_t new_mode = set_servers_from_dhcp ? 1 : 0;
|
||||||
|
if (sntp_set_servers_from_dhcp != new_mode) {
|
||||||
|
sntp_set_servers_from_dhcp = new_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Initialize one of the NTP servers by IP address
|
||||||
|
*
|
||||||
|
* @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
||||||
|
* @param server IP address of the NTP server to set
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sntp_setserver(u8_t idx, const ip_addr_t *server)
|
||||||
|
{
|
||||||
|
if (idx < SNTP_MAX_SERVERS) {
|
||||||
|
if (server != NULL) {
|
||||||
|
sntp_servers[idx].addr = (*server);
|
||||||
|
} else {
|
||||||
|
ip_addr_set_zero(&sntp_servers[idx].addr);
|
||||||
|
}
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
sntp_servers[idx].name = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP
|
||||||
|
/**
|
||||||
|
* Initialize one of the NTP servers by IP address, required by DHCP
|
||||||
|
*
|
||||||
|
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
||||||
|
* @param dnsserver IP address of the NTP server to set
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server)
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n",
|
||||||
|
(sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
|
||||||
|
ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num));
|
||||||
|
if (sntp_set_servers_from_dhcp && num) {
|
||||||
|
u8_t i;
|
||||||
|
for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) {
|
||||||
|
ip_addr_t addr;
|
||||||
|
ip_addr_copy_from_ip4(addr, server[i]);
|
||||||
|
sntp_setserver(i, &addr);
|
||||||
|
}
|
||||||
|
for (i = num; i < SNTP_MAX_SERVERS; i++) {
|
||||||
|
sntp_setserver(i, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sntp
|
||||||
|
* Obtain one of the currently configured by IP address (or DHCP) NTP servers
|
||||||
|
*
|
||||||
|
* @param idx the index of the NTP server
|
||||||
|
* @return IP address of the indexed NTP server or "ip_addr_any" if the NTP
|
||||||
|
* server has not been configured by address (or at all).
|
||||||
|
*/
|
||||||
|
const ip_addr_t*
|
||||||
|
sntp_getserver(u8_t idx)
|
||||||
|
{
|
||||||
|
if (idx < SNTP_MAX_SERVERS) {
|
||||||
|
return &sntp_servers[idx].addr;
|
||||||
|
}
|
||||||
|
return IP_ADDR_ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SNTP_SERVER_DNS
|
||||||
|
/**
|
||||||
|
* Initialize one of the NTP servers by name
|
||||||
|
*
|
||||||
|
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
|
||||||
|
* @param dnsserver DNS name of the NTP server to set, to be resolved at contact time
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sntp_setservername(u8_t idx, char *server)
|
||||||
|
{
|
||||||
|
if (idx < SNTP_MAX_SERVERS) {
|
||||||
|
sntp_servers[idx].name = server;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain one of the currently configured by name NTP servers.
|
||||||
|
*
|
||||||
|
* @param numdns the index of the NTP server
|
||||||
|
* @return IP address of the indexed NTP server or NULL if the NTP
|
||||||
|
* server has not been configured by name (or at all)
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
sntp_getservername(u8_t idx)
|
||||||
|
{
|
||||||
|
if (idx < SNTP_MAX_SERVERS) {
|
||||||
|
return sntp_servers[idx].name;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* SNTP_SERVER_DNS */
|
||||||
|
|
||||||
|
#endif /* LWIP_UDP */
|
||||||
417
ext/lwip/src/apps/tftp/tftp_server.c
Executable file
417
ext/lwip/src/apps/tftp/tftp_server.c
Executable file
@@ -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 */
|
||||||
330
ext/lwip/src/core/def.c
Normal file → Executable file
330
ext/lwip/src/core/def.c
Normal file → Executable file
@@ -1,108 +1,222 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Common functions used throughout the stack.
|
* 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
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* need to port it to your architecture and in your cc.h:
|
||||||
* All rights reserved.
|
*
|
||||||
*
|
* \#define lwip_htons(x) your_htons
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* \#define lwip_htonl(x) your_htonl
|
||||||
* are permitted provided that the following conditions are met:
|
*
|
||||||
*
|
* Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts.
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
*
|
||||||
* this list of conditions and the following disclaimer.
|
* If you \#define them to htons() and htonl(), you should
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* defining htonx/ntohx compatibility macros.
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* @defgroup sys_nonstandard Non-standard functions
|
||||||
* derived from this software without specific prior written permission.
|
* @ingroup sys_layer
|
||||||
*
|
* lwIP provides default implementations for non-standard functions.
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* These can be mapped to OS functions to reduce code footprint if desired.
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* All defines related to this section must not be placed in lwipopts.h,
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* but in arch/cc.h!
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* These options cannot be \#defined in lwipopts.h since they are not options
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* of lwIP itself, but options of the lwIP port to your system.
|
||||||
* 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
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* OF SUCH DAMAGE.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
*
|
* are permitted provided that the following conditions are met:
|
||||||
* Author: Simon Goldschmidt
|
*
|
||||||
*
|
* 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,
|
||||||
#include "lwip/opt.h"
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
#include "lwip/def.h"
|
* 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.
|
||||||
* These are reference implementations of the byte swapping functions.
|
*
|
||||||
* Again with the aim of being simple, correct and fully portable.
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* Byte swapping is the second thing you would want to optimize. You will
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* need to port it to your architecture and in your cc.h:
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
*
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
*
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
*/
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
/**
|
* Author: Simon Goldschmidt
|
||||||
* Convert an u16_t from host- to network byte order.
|
*
|
||||||
*
|
*/
|
||||||
* @param n u16_t in host byte order
|
|
||||||
* @return n in network byte order
|
#include "lwip/opt.h"
|
||||||
*/
|
#include "lwip/def.h"
|
||||||
u16_t
|
|
||||||
lwip_htons(u16_t n)
|
#include <string.h>
|
||||||
{
|
|
||||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
}
|
|
||||||
|
#if !defined(lwip_htons)
|
||||||
/**
|
/**
|
||||||
* Convert an u16_t from network- to host byte order.
|
* Convert an u16_t from host- to network byte order.
|
||||||
*
|
*
|
||||||
* @param n u16_t in network byte order
|
* @param n u16_t in host byte order
|
||||||
* @return n in host byte order
|
* @return n in network byte order
|
||||||
*/
|
*/
|
||||||
u16_t
|
u16_t
|
||||||
lwip_ntohs(u16_t n)
|
lwip_htons(u16_t n)
|
||||||
{
|
{
|
||||||
return lwip_htons(n);
|
return (u16_t)PP_HTONS(n);
|
||||||
}
|
}
|
||||||
|
#endif /* lwip_htons */
|
||||||
/**
|
|
||||||
* Convert an u32_t from host- to network byte order.
|
#if !defined(lwip_htonl)
|
||||||
*
|
/**
|
||||||
* @param n u32_t in host byte order
|
* Convert an u32_t from host- to network byte order.
|
||||||
* @return n in network byte order
|
*
|
||||||
*/
|
* @param n u32_t in host byte order
|
||||||
u32_t
|
* @return n in network byte order
|
||||||
lwip_htonl(u32_t n)
|
*/
|
||||||
{
|
u32_t
|
||||||
return ((n & 0xff) << 24) |
|
lwip_htonl(u32_t n)
|
||||||
((n & 0xff00) << 8) |
|
{
|
||||||
((n & 0xff0000UL) >> 8) |
|
return (u32_t)PP_HTONL(n);
|
||||||
((n & 0xff000000UL) >> 24);
|
}
|
||||||
}
|
#endif /* lwip_htonl */
|
||||||
|
|
||||||
/**
|
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||||
* Convert an u32_t from network- to host byte order.
|
|
||||||
*
|
#ifndef lwip_strnstr
|
||||||
* @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.
|
||||||
u32_t
|
* This can be \#defined to strnstr() depending on your platform port.
|
||||||
lwip_ntohl(u32_t n)
|
*/
|
||||||
{
|
char*
|
||||||
return lwip_htonl(n);
|
lwip_strnstr(const char* buffer, const char* token, size_t n)
|
||||||
}
|
{
|
||||||
|
const char* p;
|
||||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
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
|
||||||
|
|
||||||
|
#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
|
||||||
|
|||||||
3075
ext/lwip/src/core/dns.c
Normal file → Executable file
3075
ext/lwip/src/core/dns.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1221
ext/lwip/src/core/inet_chksum.c
Normal file → Executable file
1221
ext/lwip/src/core/inet_chksum.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
773
ext/lwip/src/core/init.c
Normal file → Executable file
773
ext/lwip/src/core/init.c
Normal file → Executable file
@@ -1,388 +1,385 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Modules initialization
|
* Modules initialization
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
#include "lwip/opt.h"
|
||||||
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
|
|
||||||
* @ingroup lwip
|
#include "lwip/init.h"
|
||||||
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
|
#include "lwip/stats.h"
|
||||||
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
|
#include "lwip/sys.h"
|
||||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
#include "lwip/mem.h"
|
||||||
* context and put them into a queue which is processed from mainloop.\n
|
#include "lwip/memp.h"
|
||||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
#include "lwip/pbuf.h"
|
||||||
* Porting: implement all functions in @ref sys_time and @ref sys_prot.\n
|
#include "lwip/netif.h"
|
||||||
* You can only use @ref callbackstyle_api in this mode.
|
#include "lwip/sockets.h"
|
||||||
*
|
#include "lwip/ip.h"
|
||||||
* @defgroup lwip_os OS mode (TCPIP thread)
|
#include "lwip/raw.h"
|
||||||
* @ingroup lwip
|
#include "lwip/udp.h"
|
||||||
* Use this mode if you run an OS on your system. It is recommended to
|
#include "lwip/priv/tcp_priv.h"
|
||||||
* use an RTOS that correctly handles priority inversion and
|
#include "lwip/igmp.h"
|
||||||
* to use LWIP_TCPIP_CORE_LOCKING.\n
|
#include "lwip/dns.h"
|
||||||
* Porting: implement all functions in @ref sys_layer.\n
|
#include "lwip/timeouts.h"
|
||||||
* You can use @ref callbackstyle_api together with \#define tcpip_callback,
|
#include "lwip/etharp.h"
|
||||||
* and all @ref threadsafe_api.
|
#include "lwip/ip6.h"
|
||||||
*/
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/api.h"
|
||||||
|
|
||||||
#include "lwip/init.h"
|
#include "netif/ppp/ppp_opts.h"
|
||||||
#include "lwip/stats.h"
|
#include "netif/ppp/ppp_impl.h"
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/mem.h"
|
#ifndef LWIP_SKIP_PACKING_CHECK
|
||||||
#include "lwip/memp.h"
|
|
||||||
#include "lwip/pbuf.h"
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
#include "lwip/netif.h"
|
# include "arch/bpstruct.h"
|
||||||
#include "lwip/sockets.h"
|
#endif
|
||||||
#include "lwip/ip.h"
|
PACK_STRUCT_BEGIN
|
||||||
#include "lwip/raw.h"
|
struct packed_struct_test
|
||||||
#include "lwip/udp.h"
|
{
|
||||||
#include "lwip/priv/tcp_priv.h"
|
PACK_STRUCT_FLD_8(u8_t dummy1);
|
||||||
#include "lwip/autoip.h"
|
PACK_STRUCT_FIELD(u32_t dummy2);
|
||||||
#include "lwip/igmp.h"
|
} PACK_STRUCT_STRUCT;
|
||||||
#include "lwip/dns.h"
|
PACK_STRUCT_END
|
||||||
#include "lwip/timeouts.h"
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
#include "lwip/etharp.h"
|
# include "arch/epstruct.h"
|
||||||
#include "lwip/ip6.h"
|
#endif
|
||||||
#include "lwip/nd6.h"
|
#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5
|
||||||
#include "lwip/mld6.h"
|
|
||||||
#include "lwip/api.h"
|
#endif
|
||||||
|
|
||||||
#include "netif/ppp/ppp_opts.h"
|
/* Compile-time sanity checks for configuration errors.
|
||||||
#include "netif/ppp/ppp_impl.h"
|
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||||
|
*/
|
||||||
/* Compile-time sanity checks for configuration errors.
|
#ifndef BYTE_ORDER
|
||||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
|
||||||
*/
|
#endif
|
||||||
#ifndef BYTE_ORDER
|
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
||||||
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
|
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
#if (!LWIP_UDP && LWIP_UDPLITE)
|
||||||
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!LWIP_UDP && LWIP_UDPLITE)
|
#if (!LWIP_UDP && LWIP_DHCP)
|
||||||
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
|
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!LWIP_UDP && LWIP_DHCP)
|
#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
|
||||||
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
#error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
|
#if (!LWIP_UDP && LWIP_DNS)
|
||||||
#error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!LWIP_UDP && LWIP_DNS)
|
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
|
||||||
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
|
||||||
#endif
|
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
|
||||||
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
|
#endif
|
||||||
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
|
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
|
||||||
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
|
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
|
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
|
||||||
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
|
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
|
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
|
||||||
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
|
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
|
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
||||||
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
|
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
|
||||||
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
|
#if (LWIP_IGMP && !LWIP_IPV4)
|
||||||
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
|
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_IGMP && !LWIP_IPV4)
|
#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
|
||||||
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
|
#error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
|
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
||||||
#error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
|
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
||||||
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
|
||||||
#endif
|
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
||||||
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
#endif
|
||||||
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
|
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
||||||
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
||||||
#endif
|
#endif
|
||||||
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
#endif /* !MEMP_MEM_MALLOC */
|
||||||
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
#if LWIP_WND_SCALE
|
||||||
#endif
|
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
#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"
|
||||||
#if LWIP_WND_SCALE
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
|
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
|
||||||
#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"
|
#error "The maximum valid window scale value is 14!"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
|
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
||||||
#error "The maximum valid window scale value is 14!"
|
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
|
||||||
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
|
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
|
#else /* LWIP_WND_SCALE */
|
||||||
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
|
#if (LWIP_TCP && (TCP_WND > 0xffff))
|
||||||
#endif
|
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
|
||||||
#else /* LWIP_WND_SCALE */
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_WND > 0xffff))
|
#endif /* LWIP_WND_SCALE */
|
||||||
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
|
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
||||||
#endif
|
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||||
#endif /* LWIP_WND_SCALE */
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
|
||||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
|
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
||||||
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
|
||||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
|
#if (LWIP_NETIF_API && (NO_SYS==1))
|
||||||
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
|
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_NETIF_API && (NO_SYS==1))
|
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
|
||||||
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
|
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
|
#if (LWIP_PPP_API && (NO_SYS==1))
|
||||||
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
|
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_PPP_API && (NO_SYS==1))
|
#if (LWIP_PPP_API && (PPP_SUPPORT==0))
|
||||||
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
|
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_PPP_API && (PPP_SUPPORT==0))
|
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
|
||||||
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
|
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
|
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
|
||||||
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
|
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
|
#if (!LWIP_ARP && LWIP_AUTOIP)
|
||||||
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
|
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (!LWIP_ARP && LWIP_AUTOIP)
|
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
|
||||||
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
|
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
|
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
|
||||||
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
|
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
|
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
|
||||||
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
|
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
|
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
||||||
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
|
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
||||||
#endif
|
#endif
|
||||||
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
||||||
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
||||||
#endif
|
#endif
|
||||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
|
||||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
|
||||||
#endif
|
#endif
|
||||||
#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
|
#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
|
||||||
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
|
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
|
||||||
#endif
|
#endif
|
||||||
#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
|
#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
|
||||||
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
|
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
|
||||||
#endif
|
#endif
|
||||||
#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
|
#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
|
||||||
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
|
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
|
||||||
#endif
|
#endif
|
||||||
#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
|
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
||||||
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
|
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
||||||
#endif
|
#endif
|
||||||
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
||||||
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
|
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
|
||||||
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
|
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
#if LWIP_NETCONN && LWIP_TCP
|
||||||
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
|
||||||
#endif
|
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
|
||||||
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
|
#endif
|
||||||
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
|
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
|
||||||
#endif
|
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
|
||||||
#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF
|
#endif
|
||||||
#error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues"
|
#endif /* LWIP_NETCONN && LWIP_TCP */
|
||||||
#endif
|
#if LWIP_SOCKET
|
||||||
#if LWIP_NETCONN && LWIP_TCP
|
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
|
||||||
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
|
#if SO_REUSEADDR != SOF_REUSEADDR
|
||||||
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
|
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
|
||||||
#endif
|
#endif
|
||||||
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
|
#if SO_KEEPALIVE != SOF_KEEPALIVE
|
||||||
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
|
#error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
|
||||||
#endif
|
#endif
|
||||||
#endif /* LWIP_NETCONN && LWIP_TCP */
|
#if SO_BROADCAST != SOF_BROADCAST
|
||||||
#if LWIP_SOCKET
|
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
|
||||||
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
|
#endif
|
||||||
#if SO_REUSEADDR != SOF_REUSEADDR
|
#endif /* LWIP_SOCKET */
|
||||||
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
|
|
||||||
#endif
|
|
||||||
#if SO_KEEPALIVE != SOF_KEEPALIVE
|
/* Compile-time checks for deprecated options.
|
||||||
#error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
|
*/
|
||||||
#endif
|
#ifdef MEMP_NUM_TCPIP_MSG
|
||||||
#if SO_BROADCAST != SOF_BROADCAST
|
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
|
||||||
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
|
#endif
|
||||||
#endif
|
#ifdef TCP_REXMIT_DEBUG
|
||||||
#endif /* LWIP_SOCKET */
|
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
|
||||||
|
#endif
|
||||||
|
#ifdef RAW_STATS
|
||||||
/* Compile-time checks for deprecated options.
|
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
|
||||||
*/
|
#endif
|
||||||
#ifdef MEMP_NUM_TCPIP_MSG
|
#ifdef ETHARP_QUEUE_FIRST
|
||||||
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
|
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCP_REXMIT_DEBUG
|
#ifdef ETHARP_ALWAYS_INSERT
|
||||||
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
|
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
|
||||||
#endif
|
#endif
|
||||||
#ifdef RAW_STATS
|
#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
|
||||||
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
|
#error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ETHARP_QUEUE_FIRST
|
|
||||||
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
|
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
|
||||||
#endif
|
#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
|
||||||
#ifdef ETHARP_ALWAYS_INSERT
|
#endif
|
||||||
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
|
#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
|
||||||
#endif
|
#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
|
||||||
#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
|
#endif
|
||||||
#error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
|
|
||||||
#endif
|
/* MEMP sanity checks */
|
||||||
|
#if MEMP_MEM_MALLOC
|
||||||
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
|
#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
|
||||||
#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
|
#if LWIP_NETCONN || LWIP_SOCKET
|
||||||
#endif
|
#if !MEMP_NUM_NETCONN && LWIP_SOCKET
|
||||||
#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
|
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
|
||||||
#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
|
#endif
|
||||||
#endif
|
#else /* MEMP_MEM_MALLOC */
|
||||||
|
#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
|
||||||
/* MEMP sanity checks */
|
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#if MEMP_MEM_MALLOC
|
#endif
|
||||||
#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
|
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
||||||
#if LWIP_NETCONN || LWIP_SOCKET
|
#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
|
||||||
#if !MEMP_NUM_NETCONN && LWIP_SOCKET
|
#if MEM_USE_POOLS
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
|
#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time"
|
||||||
#endif
|
#endif
|
||||||
#else /* MEMP_MEM_MALLOC */
|
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
||||||
#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
|
#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC"
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
|
#endif
|
||||||
#endif
|
#endif /* MEMP_MEM_MALLOC */
|
||||||
#endif /* LWIP_NETCONN || LWIP_SOCKET */
|
|
||||||
#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
|
/* TCP sanity checks */
|
||||||
#if MEM_USE_POOLS
|
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
|
||||||
#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time"
|
#if LWIP_TCP
|
||||||
#endif
|
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC"
|
#endif
|
||||||
#endif
|
#if TCP_SND_BUF < (2 * TCP_MSS)
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
|
#endif
|
||||||
/* TCP sanity checks */
|
#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
|
||||||
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
|
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#if LWIP_TCP
|
#endif
|
||||||
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
#if TCP_SNDLOWAT >= TCP_SND_BUF
|
||||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#endif
|
#endif
|
||||||
#if TCP_SND_BUF < (2 * TCP_MSS)
|
#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
|
||||||
#endif
|
#endif
|
||||||
#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
|
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
|
||||||
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#endif
|
#endif
|
||||||
#if TCP_SNDLOWAT >= TCP_SND_BUF
|
#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: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
#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
|
#endif
|
||||||
#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
|
#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_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
|
#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
|
#endif
|
||||||
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
|
#if TCP_WND < TCP_MSS
|
||||||
#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."
|
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||||
#endif
|
#endif
|
||||||
#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
|
#endif /* LWIP_TCP */
|
||||||
#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 /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
|
||||||
#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))))
|
/**
|
||||||
#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."
|
* @ingroup lwip_nosys
|
||||||
#endif
|
* Initialize all modules.
|
||||||
#if TCP_WND < TCP_MSS
|
* Use this in NO_SYS mode. Use tcpip_init() otherwise.
|
||||||
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
*/
|
||||||
#endif
|
void
|
||||||
#endif /* LWIP_TCP */
|
lwip_init(void)
|
||||||
#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
|
{
|
||||||
|
#ifndef LWIP_SKIP_CONST_CHECK
|
||||||
/**
|
int a;
|
||||||
* @ingroup lwip_nosys
|
LWIP_UNUSED_ARG(a);
|
||||||
* Initialize all modules.
|
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||||
* Use this in NO_SYS mode. Use tcpip_init() otherwise.
|
#endif
|
||||||
*/
|
#ifndef LWIP_SKIP_PACKING_CHECK
|
||||||
void
|
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
|
||||||
lwip_init(void)
|
#endif
|
||||||
{
|
|
||||||
/* Modules initialization */
|
/* Modules initialization */
|
||||||
stats_init();
|
stats_init();
|
||||||
#if !NO_SYS
|
#if !NO_SYS
|
||||||
sys_init();
|
sys_init();
|
||||||
#endif /* !NO_SYS */
|
#endif /* !NO_SYS */
|
||||||
mem_init();
|
mem_init();
|
||||||
memp_init();
|
memp_init();
|
||||||
pbuf_init();
|
pbuf_init();
|
||||||
netif_init();
|
netif_init();
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
ip_init();
|
ip_init();
|
||||||
#if LWIP_ARP
|
#if LWIP_ARP
|
||||||
etharp_init();
|
etharp_init();
|
||||||
#endif /* LWIP_ARP */
|
#endif /* LWIP_ARP */
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
raw_init();
|
raw_init();
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
udp_init();
|
udp_init();
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
tcp_init();
|
tcp_init();
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
#if LWIP_AUTOIP
|
#if LWIP_IGMP
|
||||||
autoip_init();
|
igmp_init();
|
||||||
#endif /* LWIP_AUTOIP */
|
#endif /* LWIP_IGMP */
|
||||||
#if LWIP_IGMP
|
#if LWIP_DNS
|
||||||
igmp_init();
|
dns_init();
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_DNS */
|
||||||
#if LWIP_DNS
|
#if PPP_SUPPORT
|
||||||
dns_init();
|
ppp_init();
|
||||||
#endif /* LWIP_DNS */
|
#endif
|
||||||
#if PPP_SUPPORT
|
|
||||||
ppp_init();
|
#if LWIP_TIMERS
|
||||||
#endif
|
sys_timeouts_init();
|
||||||
|
#endif /* LWIP_TIMERS */
|
||||||
#if LWIP_TIMERS
|
}
|
||||||
sys_timeouts_init();
|
|
||||||
#endif /* LWIP_TIMERS */
|
|
||||||
}
|
|
||||||
|
|||||||
248
ext/lwip/src/core/ip.c
Normal file → Executable file
248
ext/lwip/src/core/ip.c
Normal file → Executable file
@@ -1,124 +1,124 @@
|
|||||||
/**
|
/**
|
||||||
* @file ip.c
|
* @file
|
||||||
* Common IPv4 and IPv6 code
|
* Common IPv4 and IPv6 code
|
||||||
*
|
*
|
||||||
*/
|
* @defgroup ip IP
|
||||||
|
* @ingroup callbackstyle_api
|
||||||
/*
|
*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* @defgroup ip4 IPv4
|
||||||
* All rights reserved.
|
* @ingroup ip
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* @defgroup ip6 IPv6
|
||||||
* are permitted provided that the following conditions are met:
|
* @ingroup ip
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* @defgroup ipaddr IP address handling
|
||||||
* this list of conditions and the following disclaimer.
|
* @ingroup infrastructure
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
*
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* @defgroup ip4addr IPv4 only
|
||||||
* and/or other materials provided with the distribution.
|
* @ingroup ipaddr
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
*
|
||||||
* derived from this software without specific prior written permission.
|
* @defgroup ip6addr IPv6 only
|
||||||
*
|
* @ingroup ipaddr
|
||||||
* 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,
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* All rights reserved.
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
*
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* are permitted provided that the following conditions are met:
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
*
|
||||||
* OF SUCH DAMAGE.
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
*
|
* this list of conditions and the following disclaimer.
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
*
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* 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
|
||||||
* @defgroup ip4 IPv4
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* @ingroup callbackstyle_api
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
*
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* @defgroup ip6 IPv6
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* @ingroup callbackstyle_api
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
*
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* @defgroup ipaddr IP address handling
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
* @ingroup infrastructure
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
*
|
* OF SUCH DAMAGE.
|
||||||
* @defgroup ip4addr IPv4 only
|
*
|
||||||
* @ingroup ipaddr
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* @defgroup ip6addr IPv6 only
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
* @ingroup ipaddr
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV4 || LWIP_IPV6
|
#if LWIP_IPV4 || LWIP_IPV6
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
|
|
||||||
/** Global data for both IPv4 and IPv6 */
|
/** Global data for both IPv4 and IPv6 */
|
||||||
struct ip_globals ip_data;
|
struct ip_globals ip_data;
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
|
||||||
const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
|
const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup ipaddr
|
* @ingroup ipaddr
|
||||||
* Convert IP address string (both versions) to numeric.
|
* Convert IP address string (both versions) to numeric.
|
||||||
* The version is auto-detected from the string.
|
* The version is auto-detected from the string.
|
||||||
*
|
*
|
||||||
* @param cp IP address string to convert
|
* @param cp IP address string to convert
|
||||||
* @param addr conversion result is stored here
|
* @param addr conversion result is stored here
|
||||||
* @return 1 on success, 0 on error
|
* @return 1 on success, 0 on error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ipaddr_aton(const char *cp, ip_addr_t *addr)
|
ipaddr_aton(const char *cp, ip_addr_t *addr)
|
||||||
{
|
{
|
||||||
if (cp != NULL) {
|
if (cp != NULL) {
|
||||||
const char* c;
|
const char* c;
|
||||||
for (c = cp; *c != 0; c++) {
|
for (c = cp; *c != 0; c++) {
|
||||||
if (*c == ':') {
|
if (*c == ':') {
|
||||||
/* contains a colon: IPv6 address */
|
/* contains a colon: IPv6 address */
|
||||||
if (addr) {
|
if (addr) {
|
||||||
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
|
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
|
||||||
}
|
}
|
||||||
return ip6addr_aton(cp, ip_2_ip6(addr));
|
return ip6addr_aton(cp, ip_2_ip6(addr));
|
||||||
} else if (*c == '.') {
|
} else if (*c == '.') {
|
||||||
/* contains a dot: IPv4 address */
|
/* contains a dot: IPv4 address */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* call ip4addr_aton as fallback or if IPv4 was found */
|
/* call ip4addr_aton as fallback or if IPv4 was found */
|
||||||
if (addr) {
|
if (addr) {
|
||||||
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
|
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
|
||||||
}
|
}
|
||||||
return ip4addr_aton(cp, ip_2_ip4(addr));
|
return ip4addr_aton(cp, ip_2_ip4(addr));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup lwip_nosys
|
* @ingroup lwip_nosys
|
||||||
* If both IP versions are enabled, this function can dispatch packets to the correct one.
|
* If both IP versions are enabled, this function can dispatch packets to the correct one.
|
||||||
* Don't call directly, pass to netif_add() and call netif->input().
|
* Don't call directly, pass to netif_add() and call netif->input().
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
ip_input(struct pbuf *p, struct netif *inp)
|
ip_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if (IP_HDR_GET_VERSION(p->payload) == 6) {
|
if (IP_HDR_GET_VERSION(p->payload) == 6) {
|
||||||
return ip6_input(p, inp);
|
return ip6_input(p, inp);
|
||||||
}
|
}
|
||||||
return ip4_input(p, inp);
|
return ip4_input(p, inp);
|
||||||
}
|
}
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 || LWIP_IPV6 */
|
#endif /* LWIP_IPV4 || LWIP_IPV6 */
|
||||||
|
|||||||
1073
ext/lwip/src/core/ipv4/autoip.c
Normal file → Executable file
1073
ext/lwip/src/core/ipv4/autoip.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
3874
ext/lwip/src/core/ipv4/dhcp.c
Normal file → Executable file
3874
ext/lwip/src/core/ipv4/dhcp.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
2591
ext/lwip/src/core/ipv4/etharp.c
Normal file → Executable file
2591
ext/lwip/src/core/ipv4/etharp.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
790
ext/lwip/src/core/ipv4/icmp.c
Normal file → Executable file
790
ext/lwip/src/core/ipv4/icmp.c
Normal file → Executable file
@@ -1,393 +1,397 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* ICMP - Internet Control Message Protocol
|
* ICMP - Internet Control Message Protocol
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Some ICMP messages should be passed to the transport protocols. This
|
/* Some ICMP messages should be passed to the transport protocols. This
|
||||||
is not implemented. */
|
is not implemented. */
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
|
#ifdef LWIP_HOOK_FILENAME
|
||||||
* used to modify and send a response packet (and to 1 if this is not the case,
|
#include LWIP_HOOK_FILENAME
|
||||||
* e.g. when link header is stripped of when receiving) */
|
#endif
|
||||||
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
|
||||||
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
|
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
|
||||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
* used to modify and send a response packet (and to 1 if this is not the case,
|
||||||
|
* e.g. when link header is stripped of when receiving) */
|
||||||
/* The amount of data from the original packet to return in a dest-unreachable */
|
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
#define ICMP_DEST_UNREACH_DATASIZE 8
|
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
|
||||||
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||||
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
|
||||||
|
/* The amount of data from the original packet to return in a dest-unreachable */
|
||||||
/**
|
#define ICMP_DEST_UNREACH_DATASIZE 8
|
||||||
* Processes ICMP input packets, called from ip_input().
|
|
||||||
*
|
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
||||||
* Currently only processes icmp echo requests and sends
|
|
||||||
* out the echo response.
|
/**
|
||||||
*
|
* Processes ICMP input packets, called from ip_input().
|
||||||
* @param p the icmp echo request packet, p->payload pointing to the icmp header
|
*
|
||||||
* @param inp the netif on which this packet was received
|
* Currently only processes icmp echo requests and sends
|
||||||
*/
|
* out the echo response.
|
||||||
void
|
*
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
* @param p the icmp echo request packet, p->payload pointing to the icmp header
|
||||||
{
|
* @param inp the netif on which this packet was received
|
||||||
u8_t type;
|
*/
|
||||||
#ifdef LWIP_DEBUG
|
void
|
||||||
u8_t code;
|
icmp_input(struct pbuf *p, struct netif *inp)
|
||||||
#endif /* LWIP_DEBUG */
|
{
|
||||||
struct icmp_echo_hdr *iecho;
|
u8_t type;
|
||||||
const struct ip_hdr *iphdr_in;
|
#ifdef LWIP_DEBUG
|
||||||
s16_t hlen;
|
u8_t code;
|
||||||
const ip4_addr_t* src;
|
#endif /* LWIP_DEBUG */
|
||||||
|
struct icmp_echo_hdr *iecho;
|
||||||
ICMP_STATS_INC(icmp.recv);
|
const struct ip_hdr *iphdr_in;
|
||||||
MIB2_STATS_INC(mib2.icmpinmsgs);
|
u16_t hlen;
|
||||||
|
const ip4_addr_t* src;
|
||||||
iphdr_in = ip4_current_header();
|
|
||||||
hlen = IPH_HL(iphdr_in) * 4;
|
ICMP_STATS_INC(icmp.recv);
|
||||||
if (hlen < IP_HLEN) {
|
MIB2_STATS_INC(mib2.icmpinmsgs);
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen));
|
|
||||||
goto lenerr;
|
iphdr_in = ip4_current_header();
|
||||||
}
|
hlen = IPH_HL(iphdr_in) * 4;
|
||||||
if (p->len < sizeof(u16_t)*2) {
|
if (hlen < IP_HLEN) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen));
|
||||||
goto lenerr;
|
goto lenerr;
|
||||||
}
|
}
|
||||||
|
if (p->len < sizeof(u16_t)*2) {
|
||||||
type = *((u8_t *)p->payload);
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||||
#ifdef LWIP_DEBUG
|
goto lenerr;
|
||||||
code = *(((u8_t *)p->payload)+1);
|
}
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
switch (type) {
|
type = *((u8_t *)p->payload);
|
||||||
case ICMP_ER:
|
#ifdef LWIP_DEBUG
|
||||||
/* This is OK, echo reply might have been parsed by a raw PCB
|
code = *(((u8_t *)p->payload)+1);
|
||||||
(as obviously, an echo request has been sent, too). */
|
#endif /* LWIP_DEBUG */
|
||||||
MIB2_STATS_INC(mib2.icmpinechoreps);
|
switch (type) {
|
||||||
break;
|
case ICMP_ER:
|
||||||
case ICMP_ECHO:
|
/* This is OK, echo reply might have been parsed by a raw PCB
|
||||||
MIB2_STATS_INC(mib2.icmpinechos);
|
(as obviously, an echo request has been sent, too). */
|
||||||
src = ip4_current_dest_addr();
|
MIB2_STATS_INC(mib2.icmpinechoreps);
|
||||||
/* multicast destination address? */
|
break;
|
||||||
if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
|
case ICMP_ECHO:
|
||||||
#if LWIP_MULTICAST_PING
|
MIB2_STATS_INC(mib2.icmpinechos);
|
||||||
/* For multicast, use address of receiving interface as source address */
|
src = ip4_current_dest_addr();
|
||||||
src = netif_ip4_addr(inp);
|
/* multicast destination address? */
|
||||||
#else /* LWIP_MULTICAST_PING */
|
if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n"));
|
#if LWIP_MULTICAST_PING
|
||||||
goto icmperr;
|
/* For multicast, use address of receiving interface as source address */
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
src = netif_ip4_addr(inp);
|
||||||
}
|
#else /* LWIP_MULTICAST_PING */
|
||||||
/* broadcast destination address? */
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n"));
|
||||||
if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) {
|
goto icmperr;
|
||||||
#if LWIP_BROADCAST_PING
|
#endif /* LWIP_MULTICAST_PING */
|
||||||
/* For broadcast, use address of receiving interface as source address */
|
}
|
||||||
src = netif_ip4_addr(inp);
|
/* broadcast destination address? */
|
||||||
#else /* LWIP_BROADCAST_PING */
|
if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n"));
|
#if LWIP_BROADCAST_PING
|
||||||
goto icmperr;
|
/* For broadcast, use address of receiving interface as source address */
|
||||||
#endif /* LWIP_BROADCAST_PING */
|
src = netif_ip4_addr(inp);
|
||||||
}
|
#else /* LWIP_BROADCAST_PING */
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n"));
|
||||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
goto icmperr;
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
#endif /* LWIP_BROADCAST_PING */
|
||||||
goto lenerr;
|
}
|
||||||
}
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||||
#if CHECKSUM_CHECK_ICMP
|
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||||
if (inet_chksum_pbuf(p) != 0) {
|
goto lenerr;
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
|
}
|
||||||
pbuf_free(p);
|
#if CHECKSUM_CHECK_ICMP
|
||||||
ICMP_STATS_INC(icmp.chkerr);
|
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
if (inet_chksum_pbuf(p) != 0) {
|
||||||
return;
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
|
||||||
}
|
pbuf_free(p);
|
||||||
}
|
ICMP_STATS_INC(icmp.chkerr);
|
||||||
#endif
|
MIB2_STATS_INC(mib2.icmpinerrors);
|
||||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
return;
|
||||||
if (pbuf_header(p, (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
|
#endif
|
||||||
*/
|
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
struct pbuf *r;
|
if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
||||||
/* allocate new packet buffer with space for link headers */
|
/* p is not big enough to contain link headers
|
||||||
r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM);
|
* allocate a new one and copy p into it
|
||||||
if (r == NULL) {
|
*/
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
|
struct pbuf *r;
|
||||||
goto icmperr;
|
/* allocate new packet buffer with space for link headers */
|
||||||
}
|
r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM);
|
||||||
if (r->len < hlen + sizeof(struct icmp_echo_hdr)) {
|
if (r == NULL) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
|
||||||
pbuf_free(r);
|
goto icmperr;
|
||||||
goto icmperr;
|
}
|
||||||
}
|
if (r->len < hlen + sizeof(struct icmp_echo_hdr)) {
|
||||||
/* copy the ip header */
|
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header"));
|
||||||
MEMCPY(r->payload, iphdr_in, hlen);
|
pbuf_free(r);
|
||||||
/* switch r->payload back to icmp header (cannot fail) */
|
goto icmperr;
|
||||||
if (pbuf_header(r, -hlen)) {
|
}
|
||||||
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
/* copy the ip header */
|
||||||
pbuf_free(r);
|
MEMCPY(r->payload, iphdr_in, hlen);
|
||||||
goto icmperr;
|
/* switch r->payload back to icmp header (cannot fail) */
|
||||||
}
|
if (pbuf_header(r, (s16_t)-hlen)) {
|
||||||
/* copy the rest of the packet without ip header */
|
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
||||||
if (pbuf_copy(r, p) != ERR_OK) {
|
pbuf_free(r);
|
||||||
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed"));
|
goto icmperr;
|
||||||
pbuf_free(r);
|
}
|
||||||
goto icmperr;
|
/* copy the rest of the packet without ip header */
|
||||||
}
|
if (pbuf_copy(r, p) != ERR_OK) {
|
||||||
/* free the original p */
|
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed"));
|
||||||
pbuf_free(p);
|
pbuf_free(r);
|
||||||
/* we now have an identical copy of p that has room for link headers */
|
goto icmperr;
|
||||||
p = r;
|
}
|
||||||
} else {
|
/* free the original p */
|
||||||
/* restore p->payload to point to icmp header (cannot fail) */
|
pbuf_free(p);
|
||||||
if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
/* we now have an identical copy of p that has room for link headers */
|
||||||
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
p = r;
|
||||||
goto icmperr;
|
} else {
|
||||||
}
|
/* restore p->payload to point to icmp header (cannot fail) */
|
||||||
}
|
if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
||||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
||||||
/* At this point, all checks are OK. */
|
goto icmperr;
|
||||||
/* 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;
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||||
if (pbuf_header(p, hlen)) {
|
/* At this point, all checks are OK. */
|
||||||
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
|
/* We generate an answer by switching the dest and src ip addresses,
|
||||||
} else {
|
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||||
err_t ret;
|
iecho = (struct icmp_echo_hdr *)p->payload;
|
||||||
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
|
if (pbuf_header(p, (s16_t)hlen)) {
|
||||||
ip4_addr_copy(iphdr->src, *src);
|
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
|
||||||
ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
|
} else {
|
||||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
err_t ret;
|
||||||
#if CHECKSUM_GEN_ICMP
|
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
|
ip4_addr_copy(iphdr->src, *src);
|
||||||
/* adjust the checksum */
|
ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
|
||||||
if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
|
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
|
#if CHECKSUM_GEN_ICMP
|
||||||
} else {
|
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
|
||||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
|
/* adjust the checksum */
|
||||||
}
|
if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
|
||||||
}
|
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
|
||||||
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
} else {
|
||||||
else {
|
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
|
||||||
iecho->chksum = 0;
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
#if LWIP_CHECKSUM_CTRL_PER_NETIF
|
||||||
#else /* CHECKSUM_GEN_ICMP */
|
else {
|
||||||
iecho->chksum = 0;
|
iecho->chksum = 0;
|
||||||
#endif /* CHECKSUM_GEN_ICMP */
|
}
|
||||||
|
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
|
||||||
/* Set the correct TTL and recalculate the header checksum. */
|
#else /* CHECKSUM_GEN_ICMP */
|
||||||
IPH_TTL_SET(iphdr, ICMP_TTL);
|
iecho->chksum = 0;
|
||||||
IPH_CHKSUM_SET(iphdr, 0);
|
#endif /* CHECKSUM_GEN_ICMP */
|
||||||
#if CHECKSUM_GEN_IP
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
|
/* Set the correct TTL and recalculate the header checksum. */
|
||||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen));
|
IPH_TTL_SET(iphdr, ICMP_TTL);
|
||||||
}
|
IPH_CHKSUM_SET(iphdr, 0);
|
||||||
#endif /* CHECKSUM_GEN_IP */
|
#if CHECKSUM_GEN_IP
|
||||||
|
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen));
|
||||||
/* increase number of messages attempted to send */
|
}
|
||||||
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
#endif /* CHECKSUM_GEN_IP */
|
||||||
/* increase number of echo replies attempted to send */
|
|
||||||
MIB2_STATS_INC(mib2.icmpoutechoreps);
|
ICMP_STATS_INC(icmp.xmit);
|
||||||
|
/* increase number of messages attempted to send */
|
||||||
/* send an ICMP packet */
|
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
||||||
ret = ip4_output_if(p, src, IP_HDRINCL,
|
/* increase number of echo replies attempted to send */
|
||||||
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
|
MIB2_STATS_INC(mib2.icmpoutechoreps);
|
||||||
if (ret != ERR_OK) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret)));
|
/* send an ICMP packet */
|
||||||
}
|
ret = ip4_output_if(p, src, LWIP_IP_HDRINCL,
|
||||||
}
|
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
|
||||||
break;
|
if (ret != ERR_OK) {
|
||||||
default:
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret)));
|
||||||
if (type == ICMP_DUR) {
|
}
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
}
|
||||||
} else if (type == ICMP_TE) {
|
break;
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
default:
|
||||||
} else if (type == ICMP_PP) {
|
if (type == ICMP_DUR) {
|
||||||
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
||||||
} else if (type == ICMP_SQ) {
|
} else if (type == ICMP_TE) {
|
||||||
MIB2_STATS_INC(mib2.icmpinsrcquenchs);
|
MIB2_STATS_INC(mib2.icmpintimeexcds);
|
||||||
} else if (type == ICMP_RD) {
|
} else if (type == ICMP_PP) {
|
||||||
MIB2_STATS_INC(mib2.icmpinredirects);
|
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
||||||
} else if (type == ICMP_TS) {
|
} else if (type == ICMP_SQ) {
|
||||||
MIB2_STATS_INC(mib2.icmpintimestamps);
|
MIB2_STATS_INC(mib2.icmpinsrcquenchs);
|
||||||
} else if (type == ICMP_TSR) {
|
} else if (type == ICMP_RD) {
|
||||||
MIB2_STATS_INC(mib2.icmpintimestampreps);
|
MIB2_STATS_INC(mib2.icmpinredirects);
|
||||||
} else if (type == ICMP_AM) {
|
} else if (type == ICMP_TS) {
|
||||||
MIB2_STATS_INC(mib2.icmpinaddrmasks);
|
MIB2_STATS_INC(mib2.icmpintimestamps);
|
||||||
} else if (type == ICMP_AMR) {
|
} else if (type == ICMP_TSR) {
|
||||||
MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
|
MIB2_STATS_INC(mib2.icmpintimestampreps);
|
||||||
}
|
} else if (type == ICMP_AM) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
|
MIB2_STATS_INC(mib2.icmpinaddrmasks);
|
||||||
(s16_t)type, (s16_t)code));
|
} else if (type == ICMP_AMR) {
|
||||||
ICMP_STATS_INC(icmp.proterr);
|
MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
|
||||||
ICMP_STATS_INC(icmp.drop);
|
}
|
||||||
}
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
|
||||||
pbuf_free(p);
|
(s16_t)type, (s16_t)code));
|
||||||
return;
|
ICMP_STATS_INC(icmp.proterr);
|
||||||
lenerr:
|
ICMP_STATS_INC(icmp.drop);
|
||||||
pbuf_free(p);
|
}
|
||||||
ICMP_STATS_INC(icmp.lenerr);
|
pbuf_free(p);
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
return;
|
||||||
return;
|
lenerr:
|
||||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
pbuf_free(p);
|
||||||
icmperr:
|
ICMP_STATS_INC(icmp.lenerr);
|
||||||
pbuf_free(p);
|
MIB2_STATS_INC(mib2.icmpinerrors);
|
||||||
ICMP_STATS_INC(icmp.err);
|
return;
|
||||||
MIB2_STATS_INC(mib2.icmpinerrors);
|
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
||||||
return;
|
icmperr:
|
||||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
|
pbuf_free(p);
|
||||||
}
|
ICMP_STATS_INC(icmp.err);
|
||||||
|
MIB2_STATS_INC(mib2.icmpinerrors);
|
||||||
/**
|
return;
|
||||||
* Send an icmp 'destination unreachable' packet, called from ip_input() if
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
|
||||||
* the transport layer protocol is unknown and from udp_input() if the local
|
}
|
||||||
* port is not bound.
|
|
||||||
*
|
/**
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
* Send an icmp 'destination unreachable' packet, called from ip_input() if
|
||||||
* p->payload pointing to the IP header
|
* the transport layer protocol is unknown and from udp_input() if the local
|
||||||
* @param t type of the 'unreachable' packet
|
* port is not bound.
|
||||||
*/
|
*
|
||||||
void
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
* p->payload pointing to the IP header
|
||||||
{
|
* @param t type of the 'unreachable' packet
|
||||||
MIB2_STATS_INC(mib2.icmpoutdestunreachs);
|
*/
|
||||||
icmp_send_response(p, ICMP_DUR, t);
|
void
|
||||||
}
|
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||||
|
{
|
||||||
#if IP_FORWARD || IP_REASSEMBLY
|
MIB2_STATS_INC(mib2.icmpoutdestunreachs);
|
||||||
/**
|
icmp_send_response(p, ICMP_DUR, t);
|
||||||
* Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
|
}
|
||||||
*
|
|
||||||
* @param p the input packet for which the 'time exceeded' should be sent,
|
#if IP_FORWARD || IP_REASSEMBLY
|
||||||
* p->payload pointing to the IP header
|
/**
|
||||||
* @param t type of the 'time exceeded' packet
|
* Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
|
||||||
*/
|
*
|
||||||
void
|
* @param p the input packet for which the 'time exceeded' should be sent,
|
||||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
* p->payload pointing to the IP header
|
||||||
{
|
* @param t type of the 'time exceeded' packet
|
||||||
MIB2_STATS_INC(mib2.icmpouttimeexcds);
|
*/
|
||||||
icmp_send_response(p, ICMP_TE, t);
|
void
|
||||||
}
|
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||||
|
{
|
||||||
#endif /* IP_FORWARD || IP_REASSEMBLY */
|
MIB2_STATS_INC(mib2.icmpouttimeexcds);
|
||||||
|
icmp_send_response(p, ICMP_TE, t);
|
||||||
/**
|
}
|
||||||
* Send an icmp packet in response to an incoming packet.
|
|
||||||
*
|
#endif /* IP_FORWARD || IP_REASSEMBLY */
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
|
||||||
* p->payload pointing to the IP header
|
/**
|
||||||
* @param type Type of the ICMP header
|
* Send an icmp packet in response to an incoming packet.
|
||||||
* @param code Code of the ICMP header
|
*
|
||||||
*/
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
static void
|
* p->payload pointing to the IP header
|
||||||
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
* @param type Type of the ICMP header
|
||||||
{
|
* @param code Code of the ICMP header
|
||||||
struct pbuf *q;
|
*/
|
||||||
struct ip_hdr *iphdr;
|
static void
|
||||||
/* we can use the echo header here */
|
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||||
struct icmp_echo_hdr *icmphdr;
|
{
|
||||||
ip4_addr_t iphdr_src;
|
struct pbuf *q;
|
||||||
struct netif *netif;
|
struct ip_hdr *iphdr;
|
||||||
|
/* we can use the echo header here */
|
||||||
/* increase number of messages attempted to send */
|
struct icmp_echo_hdr *icmphdr;
|
||||||
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
ip4_addr_t iphdr_src;
|
||||||
|
struct netif *netif;
|
||||||
/* ICMP header + IP header + 8 bytes of data */
|
|
||||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
/* increase number of messages attempted to send */
|
||||||
PBUF_RAM);
|
MIB2_STATS_INC(mib2.icmpoutmsgs);
|
||||||
if (q == NULL) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
/* ICMP header + IP header + 8 bytes of data */
|
||||||
MIB2_STATS_INC(mib2.icmpouterrors);
|
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||||
return;
|
PBUF_RAM);
|
||||||
}
|
if (q == NULL) {
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
||||||
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
MIB2_STATS_INC(mib2.icmpouterrors);
|
||||||
|
return;
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
}
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||||
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
|
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
|
||||||
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);
|
iphdr = (struct ip_hdr *)p->payload;
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||||
|
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
|
||||||
icmphdr = (struct icmp_echo_hdr *)q->payload;
|
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
||||||
icmphdr->type = type;
|
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);
|
||||||
icmphdr->code = code;
|
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||||
icmphdr->id = 0;
|
|
||||||
icmphdr->seqno = 0;
|
icmphdr = (struct icmp_echo_hdr *)q->payload;
|
||||||
|
icmphdr->type = type;
|
||||||
/* copy fields from original packet */
|
icmphdr->code = code;
|
||||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
|
icmphdr->id = 0;
|
||||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
icmphdr->seqno = 0;
|
||||||
|
|
||||||
ip4_addr_copy(iphdr_src, iphdr->src);
|
/* copy fields from original packet */
|
||||||
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
|
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
|
||||||
{
|
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
||||||
ip4_addr_t iphdr_dst;
|
|
||||||
ip4_addr_copy(iphdr_dst, iphdr->dest);
|
ip4_addr_copy(iphdr_src, iphdr->src);
|
||||||
netif = ip4_route_src(&iphdr_src, &iphdr_dst);
|
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
|
||||||
}
|
{
|
||||||
#else
|
ip4_addr_t iphdr_dst;
|
||||||
netif = ip4_route(&iphdr_src);
|
ip4_addr_copy(iphdr_dst, iphdr->dest);
|
||||||
#endif
|
netif = ip4_route_src(&iphdr_src, &iphdr_dst);
|
||||||
if (netif != NULL) {
|
}
|
||||||
/* calculate checksum */
|
#else
|
||||||
icmphdr->chksum = 0;
|
netif = ip4_route(&iphdr_src);
|
||||||
#if CHECKSUM_GEN_ICMP
|
#endif
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
|
if (netif != NULL) {
|
||||||
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
/* calculate checksum */
|
||||||
}
|
icmphdr->chksum = 0;
|
||||||
#endif
|
#if CHECKSUM_GEN_ICMP
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
|
||||||
ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
|
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
||||||
}
|
}
|
||||||
pbuf_free(q);
|
#endif
|
||||||
}
|
ICMP_STATS_INC(icmp.xmit);
|
||||||
|
ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
|
||||||
#endif /* LWIP_IPV4 && LWIP_ICMP */
|
}
|
||||||
|
pbuf_free(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_ICMP */
|
||||||
|
|||||||
1641
ext/lwip/src/core/ipv4/igmp.c
Normal file → Executable file
1641
ext/lwip/src/core/ipv4/igmp.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
2159
ext/lwip/src/core/ipv4/ip4.c
Normal file → Executable file
2159
ext/lwip/src/core/ipv4/ip4.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
662
ext/lwip/src/core/ipv4/ip4_addr.c
Normal file → Executable file
662
ext/lwip/src/core/ipv4/ip4_addr.c
Normal file → Executable file
@@ -1,331 +1,331 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* This is the IPv4 address tools implementation.
|
* This is the IPv4 address tools implementation.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.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_any = IPADDR4_INIT(IPADDR_ANY);
|
||||||
const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
|
const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an address is a broadcast address on a network interface
|
* Determine if an address is a broadcast address on a network interface
|
||||||
*
|
*
|
||||||
* @param addr address to be checked
|
* @param addr address to be checked
|
||||||
* @param netif the network interface against which the address is checked
|
* @param netif the network interface against which the address is checked
|
||||||
* @return returns non-zero if the address is a broadcast address
|
* @return returns non-zero if the address is a broadcast address
|
||||||
*/
|
*/
|
||||||
u8_t
|
u8_t
|
||||||
ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif)
|
ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif)
|
||||||
{
|
{
|
||||||
ip4_addr_t ipaddr;
|
ip4_addr_t ipaddr;
|
||||||
ip4_addr_set_u32(&ipaddr, addr);
|
ip4_addr_set_u32(&ipaddr, addr);
|
||||||
|
|
||||||
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
||||||
if ((~addr == IPADDR_ANY) ||
|
if ((~addr == IPADDR_ANY) ||
|
||||||
(addr == IPADDR_ANY)) {
|
(addr == IPADDR_ANY)) {
|
||||||
return 1;
|
return 1;
|
||||||
/* no broadcast support on this network interface? */
|
/* no broadcast support on this network interface? */
|
||||||
} else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
|
} else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
|
||||||
/* the given address cannot be a broadcast address
|
/* the given address cannot be a broadcast address
|
||||||
* nor can we check against any broadcast addresses */
|
* nor can we check against any broadcast addresses */
|
||||||
return 0;
|
return 0;
|
||||||
/* address matches network interface address exactly? => no broadcast */
|
/* address matches network interface address exactly? => no broadcast */
|
||||||
} else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) {
|
} else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) {
|
||||||
return 0;
|
return 0;
|
||||||
/* on the same (sub) network... */
|
/* on the same (sub) network... */
|
||||||
} else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif))
|
} else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif))
|
||||||
/* ...and host identifier bits are all ones? =>... */
|
/* ...and host identifier bits are all ones? =>... */
|
||||||
&& ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) ==
|
&& ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) ==
|
||||||
(IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) {
|
(IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) {
|
||||||
/* => network broadcast address */
|
/* => network broadcast address */
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks if a netmask is valid (starting with ones, then only zeros)
|
/** Checks if a netmask is valid (starting with ones, then only zeros)
|
||||||
*
|
*
|
||||||
* @param netmask the IPv4 netmask to check (in network byte order!)
|
* @param netmask the IPv4 netmask to check (in network byte order!)
|
||||||
* @return 1 if the netmask is valid, 0 if it is not
|
* @return 1 if the netmask is valid, 0 if it is not
|
||||||
*/
|
*/
|
||||||
u8_t
|
u8_t
|
||||||
ip4_addr_netmask_valid(u32_t netmask)
|
ip4_addr_netmask_valid(u32_t netmask)
|
||||||
{
|
{
|
||||||
u32_t mask;
|
u32_t mask;
|
||||||
u32_t nm_hostorder = lwip_htonl(netmask);
|
u32_t nm_hostorder = lwip_htonl(netmask);
|
||||||
|
|
||||||
/* first, check for the first zero */
|
/* first, check for the first zero */
|
||||||
for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
|
for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
|
||||||
if ((nm_hostorder & mask) == 0) {
|
if ((nm_hostorder & mask) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* then check that there is no one */
|
/* then check that there is no one */
|
||||||
for (; mask != 0; mask >>= 1) {
|
for (; mask != 0; mask >>= 1) {
|
||||||
if ((nm_hostorder & mask) != 0) {
|
if ((nm_hostorder & mask) != 0) {
|
||||||
/* there is a one after the first zero -> invalid */
|
/* there is a one after the first zero -> invalid */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* no one after the first zero -> valid */
|
/* no one after the first zero -> valid */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here for now until needed in other places in lwIP */
|
/* Here for now until needed in other places in lwIP */
|
||||||
#ifndef isprint
|
#ifndef isprint
|
||||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||||
#define isdigit(c) in_range(c, '0', '9')
|
#define isdigit(c) in_range(c, '0', '9')
|
||||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||||
#define islower(c) in_range(c, 'a', 'z')
|
#define islower(c) in_range(c, 'a', 'z')
|
||||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ascii internet address interpretation routine.
|
* Ascii internet address interpretation routine.
|
||||||
* The value returned is in network order.
|
* The value returned is in network order.
|
||||||
*
|
*
|
||||||
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
|
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
|
||||||
* @return ip address in network order
|
* @return ip address in network order
|
||||||
*/
|
*/
|
||||||
u32_t
|
u32_t
|
||||||
ipaddr_addr(const char *cp)
|
ipaddr_addr(const char *cp)
|
||||||
{
|
{
|
||||||
ip4_addr_t val;
|
ip4_addr_t val;
|
||||||
|
|
||||||
if (ip4addr_aton(cp, &val)) {
|
if (ip4addr_aton(cp, &val)) {
|
||||||
return ip4_addr_get_u32(&val);
|
return ip4_addr_get_u32(&val);
|
||||||
}
|
}
|
||||||
return (IPADDR_NONE);
|
return (IPADDR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether "cp" is a valid ascii representation
|
* Check whether "cp" is a valid ascii representation
|
||||||
* of an Internet address and convert to a binary address.
|
* of an Internet address and convert to a binary address.
|
||||||
* Returns 1 if the address is valid, 0 if not.
|
* Returns 1 if the address is valid, 0 if not.
|
||||||
* This replaces inet_addr, the return value from which
|
* This replaces inet_addr, the return value from which
|
||||||
* cannot distinguish between failure and a local broadcast address.
|
* cannot distinguish between failure and a local broadcast address.
|
||||||
*
|
*
|
||||||
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
|
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
|
||||||
* @param addr pointer to which to save the ip address in network order
|
* @param addr pointer to which to save the ip address in network order
|
||||||
* @return 1 if cp could be converted to addr, 0 on failure
|
* @return 1 if cp could be converted to addr, 0 on failure
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
||||||
{
|
{
|
||||||
u32_t val;
|
u32_t val;
|
||||||
u8_t base;
|
u8_t base;
|
||||||
char c;
|
char c;
|
||||||
u32_t parts[4];
|
u32_t parts[4];
|
||||||
u32_t *pp = parts;
|
u32_t *pp = parts;
|
||||||
|
|
||||||
c = *cp;
|
c = *cp;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/*
|
/*
|
||||||
* Collect number up to ``.''.
|
* Collect number up to ``.''.
|
||||||
* Values are specified as for C:
|
* Values are specified as for C:
|
||||||
* 0x=hex, 0=octal, 1-9=decimal.
|
* 0x=hex, 0=octal, 1-9=decimal.
|
||||||
*/
|
*/
|
||||||
if (!isdigit(c)) {
|
if (!isdigit(c)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
val = 0;
|
val = 0;
|
||||||
base = 10;
|
base = 10;
|
||||||
if (c == '0') {
|
if (c == '0') {
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
if (c == 'x' || c == 'X') {
|
if (c == 'x' || c == 'X') {
|
||||||
base = 16;
|
base = 16;
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else {
|
} else {
|
||||||
base = 8;
|
base = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
val = (val * base) + (int)(c - '0');
|
val = (val * base) + (u32_t)(c - '0');
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else if (base == 16 && isxdigit(c)) {
|
} 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;
|
c = *++cp;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
/*
|
/*
|
||||||
* Internet format:
|
* Internet format:
|
||||||
* a.b.c.d
|
* a.b.c.d
|
||||||
* a.b.c (with c treated as 16 bits)
|
* a.b.c (with c treated as 16 bits)
|
||||||
* a.b (with b treated as 24 bits)
|
* a.b (with b treated as 24 bits)
|
||||||
*/
|
*/
|
||||||
if (pp >= parts + 3) {
|
if (pp >= parts + 3) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*pp++ = val;
|
*pp++ = val;
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Check for trailing characters.
|
* Check for trailing characters.
|
||||||
*/
|
*/
|
||||||
if (c != '\0' && !isspace(c)) {
|
if (c != '\0' && !isspace(c)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Concoct the address according to
|
* Concoct the address according to
|
||||||
* the number of parts specified.
|
* the number of parts specified.
|
||||||
*/
|
*/
|
||||||
switch (pp - parts + 1) {
|
switch (pp - parts + 1) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
return 0; /* initial nondigit */
|
return 0; /* initial nondigit */
|
||||||
|
|
||||||
case 1: /* a -- 32 bits */
|
case 1: /* a -- 32 bits */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* a.b -- 8.24 bits */
|
case 2: /* a.b -- 8.24 bits */
|
||||||
if (val > 0xffffffUL) {
|
if (val > 0xffffffUL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (parts[0] > 0xff) {
|
if (parts[0] > 0xff) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
val |= parts[0] << 24;
|
val |= parts[0] << 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* a.b.c -- 8.8.16 bits */
|
case 3: /* a.b.c -- 8.8.16 bits */
|
||||||
if (val > 0xffff) {
|
if (val > 0xffff) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
|
if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||||
if (val > 0xff) {
|
if (val > 0xff) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) {
|
if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_ASSERT("unhandled", 0);
|
LWIP_ASSERT("unhandled", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (addr) {
|
if (addr) {
|
||||||
ip4_addr_set_u32(addr, htonl(val));
|
ip4_addr_set_u32(addr, lwip_htonl(val));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert numeric IP address into decimal dotted ASCII representation.
|
* Convert numeric IP address into decimal dotted ASCII representation.
|
||||||
* returns ptr to static buffer; not reentrant!
|
* returns ptr to static buffer; not reentrant!
|
||||||
*
|
*
|
||||||
* @param addr ip address in network order to convert
|
* @param addr ip address in network order to convert
|
||||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||||
* representation of addr
|
* representation of addr
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
ip4addr_ntoa(const ip4_addr_t *addr)
|
ip4addr_ntoa(const ip4_addr_t *addr)
|
||||||
{
|
{
|
||||||
static char str[IP4ADDR_STRLEN_MAX];
|
static char str[IP4ADDR_STRLEN_MAX];
|
||||||
return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
|
return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
||||||
*
|
*
|
||||||
* @param addr ip address in network order to convert
|
* @param addr ip address in network order to convert
|
||||||
* @param buf target buffer where the string is stored
|
* @param buf target buffer where the string is stored
|
||||||
* @param buflen length of buf
|
* @param buflen length of buf
|
||||||
* @return either pointer to buf which now holds the ASCII
|
* @return either pointer to buf which now holds the ASCII
|
||||||
* representation of addr or NULL if buf was too small
|
* representation of addr or NULL if buf was too small
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
|
ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
u32_t s_addr;
|
u32_t s_addr;
|
||||||
char inv[3];
|
char inv[3];
|
||||||
char *rp;
|
char *rp;
|
||||||
u8_t *ap;
|
u8_t *ap;
|
||||||
u8_t rem;
|
u8_t rem;
|
||||||
u8_t n;
|
u8_t n;
|
||||||
u8_t i;
|
u8_t i;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
s_addr = ip4_addr_get_u32(addr);
|
s_addr = ip4_addr_get_u32(addr);
|
||||||
|
|
||||||
rp = buf;
|
rp = buf;
|
||||||
ap = (u8_t *)&s_addr;
|
ap = (u8_t *)&s_addr;
|
||||||
for (n = 0; n < 4; n++) {
|
for (n = 0; n < 4; n++) {
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
rem = *ap % (u8_t)10;
|
rem = *ap % (u8_t)10;
|
||||||
*ap /= (u8_t)10;
|
*ap /= (u8_t)10;
|
||||||
inv[i++] = '0' + rem;
|
inv[i++] = (char)('0' + rem);
|
||||||
} while (*ap);
|
} while (*ap);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
if (len++ >= buflen) {
|
if (len++ >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*rp++ = inv[i];
|
*rp++ = inv[i];
|
||||||
}
|
}
|
||||||
if (len++ >= buflen) {
|
if (len++ >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*rp++ = '.';
|
*rp++ = '.';
|
||||||
ap++;
|
ap++;
|
||||||
}
|
}
|
||||||
*--rp = 0;
|
*--rp = 0;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
|
|||||||
1728
ext/lwip/src/core/ipv4/ip4_frag.c
Normal file → Executable file
1728
ext/lwip/src/core/ipv4/ip4_frag.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
|||||||
IPv6 support in lwIP is very experimental.
|
|
||||||
100
ext/lwip/src/core/ipv6/dhcp6.c
Normal file → Executable file
100
ext/lwip/src/core/ipv6/dhcp6.c
Normal file → Executable file
@@ -1,50 +1,50 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* DHCPv6.
|
* DHCPv6.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
* <delamer@inicotech.com>
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */
|
#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */
|
||||||
|
|||||||
275
ext/lwip/src/core/ipv6/ethip6.c
Normal file → Executable file
275
ext/lwip/src/core/ipv6/ethip6.c
Normal file → Executable file
@@ -1,157 +1,118 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
* <delamer@inicotech.com>
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ETHERNET
|
||||||
|
|
||||||
#include "lwip/ethip6.h"
|
#include "lwip/ethip6.h"
|
||||||
#include "lwip/nd6.h"
|
#include "lwip/nd6.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip6.h"
|
#include "lwip/ip6.h"
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/icmp6.h"
|
#include "lwip/icmp6.h"
|
||||||
#include "netif/ethernet.h"
|
#include "lwip/prot/ethernet.h"
|
||||||
|
#include "netif/ethernet.h"
|
||||||
#include <string.h>
|
|
||||||
|
#include <string.h>
|
||||||
/**
|
|
||||||
* Send an IPv6 packet on the network using netif->linkoutput
|
/**
|
||||||
* The ethernet header is filled in before sending.
|
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
||||||
*
|
*
|
||||||
* @params netif the lwIP network interface on which to send the packet
|
* For IPv6 multicast, corresponding Ethernet addresses
|
||||||
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
* are selected and the packet is transmitted on the link.
|
||||||
* @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
|
* For unicast addresses, ask the ND6 module what to do. It will either let us
|
||||||
* @return ERR_OK if the packet was sent, any other err_t on failure
|
* send the the packet right away, or queue the packet for later itself, unless
|
||||||
*/
|
* an error occurs.
|
||||||
static err_t
|
*
|
||||||
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
* @todo anycast addresses
|
||||||
{
|
*
|
||||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
* @param netif The lwIP network interface which the IP packet will be sent on.
|
||||||
|
* @param q The pbuf(s) containing the IP packet to be sent.
|
||||||
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
* @param ip6addr The IP address of the packet destination.
|
||||||
(netif->hwaddr_len == 6));
|
*
|
||||||
SMEMCPY(ðhdr->dest, dst, 6);
|
* @return
|
||||||
SMEMCPY(ðhdr->src, src, 6);
|
* - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue.
|
||||||
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
*/
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
err_t
|
||||||
/* send the packet */
|
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
||||||
return netif->linkoutput(netif, p);
|
{
|
||||||
}
|
struct eth_addr dest;
|
||||||
|
const u8_t *hwaddr;
|
||||||
/**
|
err_t result;
|
||||||
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
|
||||||
*
|
/* multicast destination IP address? */
|
||||||
* For IPv6 multicast, corresponding Ethernet addresses
|
if (ip6_addr_ismulticast(ip6addr)) {
|
||||||
* are selected and the packet is transmitted on the link.
|
/* Hash IP multicast address to MAC address.*/
|
||||||
*
|
dest.addr[0] = 0x33;
|
||||||
* For unicast addresses, ...
|
dest.addr[1] = 0x33;
|
||||||
*
|
dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0];
|
||||||
* @todo anycast addresses
|
dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1];
|
||||||
*
|
dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2];
|
||||||
* @param netif The lwIP network interface which the IP packet will be sent on.
|
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
||||||
* @param q The pbuf(s) containing the IP packet to be sent.
|
|
||||||
* @param ip6addr The IP address of the packet destination.
|
/* Send out. */
|
||||||
*
|
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||||
* @return
|
}
|
||||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
|
||||||
* or the return type of either etharp_query() or etharp_send_ip().
|
/* We have a unicast destination IP address */
|
||||||
*/
|
/* @todo anycast? */
|
||||||
err_t
|
|
||||||
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
/* Ask ND6 what to do with the packet. */
|
||||||
{
|
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
|
||||||
struct eth_addr dest;
|
if (result != ERR_OK) {
|
||||||
s8_t i;
|
return result;
|
||||||
|
}
|
||||||
/* make room for Ethernet header - should not fail */
|
|
||||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
/* If no hardware address is returned, nd6 has queued the packet for later. */
|
||||||
/* bail out */
|
if (hwaddr == NULL) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
return ERR_OK;
|
||||||
("etharp_output: could not allocate room for header.\n"));
|
}
|
||||||
return ERR_BUF;
|
|
||||||
}
|
/* Send out the packet using the returned hardware address. */
|
||||||
|
SMEMCPY(dest.addr, hwaddr, 6);
|
||||||
/* multicast destination IP address? */
|
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||||
if (ip6_addr_ismulticast(ip6addr)) {
|
}
|
||||||
/* Hash IP multicast address to MAC address.*/
|
|
||||||
dest.addr[0] = 0x33;
|
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||||
dest.addr[1] = 0x33;
|
|
||||||
dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0];
|
|
||||||
dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1];
|
|
||||||
dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2];
|
|
||||||
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
|
||||||
|
|
||||||
/* Send out. */
|
|
||||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have a unicast destination IP address */
|
|
||||||
/* @todo anycast? */
|
|
||||||
/* Get next hop record. */
|
|
||||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
|
||||||
if (i < 0) {
|
|
||||||
/* failed to get a next hop neighbor record. */
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now that we have a destination record, send or queue the packet. */
|
|
||||||
if (neighbor_cache[i].state == ND6_STALE) {
|
|
||||||
/* Switch to delay state. */
|
|
||||||
neighbor_cache[i].state = ND6_DELAY;
|
|
||||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
|
||||||
}
|
|
||||||
/* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
|
|
||||||
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
|
|
||||||
(neighbor_cache[i].state == ND6_DELAY) ||
|
|
||||||
(neighbor_cache[i].state == ND6_PROBE)) {
|
|
||||||
|
|
||||||
/* Send out. */
|
|
||||||
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
|
|
||||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
|
||||||
}
|
|
||||||
/* We should queue packet on this interface. */
|
|
||||||
pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR);
|
|
||||||
return nd6_queue_packet(i, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
699
ext/lwip/src/core/ipv6/icmp6.c
Normal file → Executable file
699
ext/lwip/src/core/ipv6/icmp6.c
Normal file → Executable file
@@ -1,349 +1,350 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* IPv6 version of ICMP, as per RFC 4443.
|
* IPv6 version of ICMP, as per RFC 4443.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
* <delamer@inicotech.com>
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/icmp6.h"
|
#include "lwip/icmp6.h"
|
||||||
#include "lwip/ip6.h"
|
#include "lwip/prot/icmp6.h"
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/ip6.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/nd6.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/mld6.h"
|
#include "lwip/nd6.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/mld6.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
#include <string.h>
|
|
||||||
|
#include <string.h>
|
||||||
#ifndef LWIP_ICMP6_DATASIZE
|
|
||||||
#define LWIP_ICMP6_DATASIZE 8
|
#ifndef LWIP_ICMP6_DATASIZE
|
||||||
#endif
|
#define LWIP_ICMP6_DATASIZE 8
|
||||||
#if LWIP_ICMP6_DATASIZE == 0
|
#endif
|
||||||
#define LWIP_ICMP6_DATASIZE 8
|
#if LWIP_ICMP6_DATASIZE == 0
|
||||||
#endif
|
#define LWIP_ICMP6_DATASIZE 8
|
||||||
|
#endif
|
||||||
/* Forward declarations */
|
|
||||||
static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
|
/* Forward declarations */
|
||||||
|
static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an input ICMPv6 message. Called by ip6_input.
|
/**
|
||||||
*
|
* Process an input ICMPv6 message. Called by ip6_input.
|
||||||
* Will generate a reply for echo requests. Other messages are forwarded
|
*
|
||||||
* to nd6_input, or mld6_input.
|
* Will generate a reply for echo requests. Other messages are forwarded
|
||||||
*
|
* to nd6_input, or mld6_input.
|
||||||
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
*
|
||||||
* @param inp the netif on which this packet was received
|
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
||||||
*/
|
* @param inp the netif on which this packet was received
|
||||||
void
|
*/
|
||||||
icmp6_input(struct pbuf *p, struct netif *inp)
|
void
|
||||||
{
|
icmp6_input(struct pbuf *p, struct netif *inp)
|
||||||
struct icmp6_hdr *icmp6hdr;
|
{
|
||||||
struct pbuf * r;
|
struct icmp6_hdr *icmp6hdr;
|
||||||
const ip6_addr_t * reply_src;
|
struct pbuf *r;
|
||||||
|
const ip6_addr_t *reply_src;
|
||||||
ICMP6_STATS_INC(icmp6.recv);
|
|
||||||
|
ICMP6_STATS_INC(icmp6.recv);
|
||||||
/* Check that ICMPv6 header fits in payload */
|
|
||||||
if (p->len < sizeof(struct icmp6_hdr)) {
|
/* Check that ICMPv6 header fits in payload */
|
||||||
/* drop short packets */
|
if (p->len < sizeof(struct icmp6_hdr)) {
|
||||||
pbuf_free(p);
|
/* drop short packets */
|
||||||
ICMP6_STATS_INC(icmp6.lenerr);
|
pbuf_free(p);
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
ICMP6_STATS_INC(icmp6.lenerr);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
|
||||||
|
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
||||||
#if CHECKSUM_CHECK_ICMP6
|
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) {
|
#if CHECKSUM_CHECK_ICMP6
|
||||||
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
|
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) {
|
||||||
ip6_current_dest_addr()) != 0) {
|
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
|
||||||
/* Checksum failed */
|
ip6_current_dest_addr()) != 0) {
|
||||||
pbuf_free(p);
|
/* Checksum failed */
|
||||||
ICMP6_STATS_INC(icmp6.chkerr);
|
pbuf_free(p);
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
ICMP6_STATS_INC(icmp6.chkerr);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_CHECK_ICMP6 */
|
}
|
||||||
|
#endif /* CHECKSUM_CHECK_ICMP6 */
|
||||||
switch (icmp6hdr->type) {
|
|
||||||
case ICMP6_TYPE_NA: /* Neighbor advertisement */
|
switch (icmp6hdr->type) {
|
||||||
case ICMP6_TYPE_NS: /* Neighbor solicitation */
|
case ICMP6_TYPE_NA: /* Neighbor advertisement */
|
||||||
case ICMP6_TYPE_RA: /* Router advertisement */
|
case ICMP6_TYPE_NS: /* Neighbor solicitation */
|
||||||
case ICMP6_TYPE_RD: /* Redirect */
|
case ICMP6_TYPE_RA: /* Router advertisement */
|
||||||
case ICMP6_TYPE_PTB: /* Packet too big */
|
case ICMP6_TYPE_RD: /* Redirect */
|
||||||
nd6_input(p, inp);
|
case ICMP6_TYPE_PTB: /* Packet too big */
|
||||||
return;
|
nd6_input(p, inp);
|
||||||
break;
|
return;
|
||||||
case ICMP6_TYPE_RS:
|
break;
|
||||||
#if LWIP_IPV6_FORWARD
|
case ICMP6_TYPE_RS:
|
||||||
/* @todo implement router functionality */
|
#if LWIP_IPV6_FORWARD
|
||||||
#endif
|
/* @todo implement router functionality */
|
||||||
break;
|
#endif
|
||||||
#if LWIP_IPV6_MLD
|
break;
|
||||||
case ICMP6_TYPE_MLQ:
|
#if LWIP_IPV6_MLD
|
||||||
case ICMP6_TYPE_MLR:
|
case ICMP6_TYPE_MLQ:
|
||||||
case ICMP6_TYPE_MLD:
|
case ICMP6_TYPE_MLR:
|
||||||
mld6_input(p, inp);
|
case ICMP6_TYPE_MLD:
|
||||||
return;
|
mld6_input(p, inp);
|
||||||
break;
|
return;
|
||||||
#endif
|
break;
|
||||||
case ICMP6_TYPE_EREQ:
|
#endif
|
||||||
#if !LWIP_MULTICAST_PING
|
case ICMP6_TYPE_EREQ:
|
||||||
/* multicast destination address? */
|
#if !LWIP_MULTICAST_PING
|
||||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
/* multicast destination address? */
|
||||||
/* drop */
|
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||||
pbuf_free(p);
|
/* drop */
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
pbuf_free(p);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
}
|
return;
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
}
|
||||||
|
#endif /* LWIP_MULTICAST_PING */
|
||||||
/* Allocate reply. */
|
|
||||||
r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
|
/* Allocate reply. */
|
||||||
if (r == NULL) {
|
r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
|
||||||
/* drop */
|
if (r == NULL) {
|
||||||
pbuf_free(p);
|
/* drop */
|
||||||
ICMP6_STATS_INC(icmp6.memerr);
|
pbuf_free(p);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.memerr);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
/* Copy echo request. */
|
|
||||||
if (pbuf_copy(r, p) != ERR_OK) {
|
/* Copy echo request. */
|
||||||
/* drop */
|
if (pbuf_copy(r, p) != ERR_OK) {
|
||||||
pbuf_free(p);
|
/* drop */
|
||||||
pbuf_free(r);
|
pbuf_free(p);
|
||||||
ICMP6_STATS_INC(icmp6.err);
|
pbuf_free(r);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.err);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
/* Determine reply source IPv6 address. */
|
|
||||||
#if LWIP_MULTICAST_PING
|
/* Determine reply source IPv6 address. */
|
||||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
#if LWIP_MULTICAST_PING
|
||||||
reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr()));
|
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||||
if (reply_src == NULL) {
|
reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr()));
|
||||||
/* drop */
|
if (reply_src == NULL) {
|
||||||
pbuf_free(p);
|
/* drop */
|
||||||
pbuf_free(r);
|
pbuf_free(p);
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
pbuf_free(r);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.rterr);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
else
|
||||||
{
|
#endif /* LWIP_MULTICAST_PING */
|
||||||
reply_src = ip6_current_dest_addr();
|
{
|
||||||
}
|
reply_src = ip6_current_dest_addr();
|
||||||
|
}
|
||||||
/* Set fields in reply. */
|
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
/* Set fields in reply. */
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
||||||
#if CHECKSUM_GEN_ICMP6
|
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
||||||
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) {
|
#if CHECKSUM_GEN_ICMP6
|
||||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) {
|
||||||
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
|
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
||||||
}
|
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
|
||||||
#endif /* CHECKSUM_GEN_ICMP6 */
|
}
|
||||||
|
#endif /* CHECKSUM_GEN_ICMP6 */
|
||||||
/* Send reply. */
|
|
||||||
ICMP6_STATS_INC(icmp6.xmit);
|
/* Send reply. */
|
||||||
ip6_output_if(r, reply_src, ip6_current_src_addr(),
|
ICMP6_STATS_INC(icmp6.xmit);
|
||||||
LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
|
ip6_output_if(r, reply_src, ip6_current_src_addr(),
|
||||||
pbuf_free(r);
|
LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
|
||||||
|
pbuf_free(r);
|
||||||
break;
|
|
||||||
default:
|
break;
|
||||||
ICMP6_STATS_INC(icmp6.proterr);
|
default:
|
||||||
ICMP6_STATS_INC(icmp6.drop);
|
ICMP6_STATS_INC(icmp6.proterr);
|
||||||
break;
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
pbuf_free(p);
|
|
||||||
}
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an icmpv6 'destination unreachable' packet.
|
/**
|
||||||
*
|
* Send an icmpv6 'destination unreachable' packet.
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
*
|
||||||
* p->payload pointing to the IPv6 header
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
* @param c ICMPv6 code for the unreachable type
|
* p->payload pointing to the IPv6 header
|
||||||
*/
|
* @param c ICMPv6 code for the unreachable type
|
||||||
void
|
*/
|
||||||
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
void
|
||||||
{
|
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
||||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
|
{
|
||||||
}
|
icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Send an icmpv6 'packet too big' packet.
|
/**
|
||||||
*
|
* Send an icmpv6 'packet too big' packet.
|
||||||
* @param p the input packet for which the 'packet too big' should be sent,
|
*
|
||||||
* p->payload pointing to the IPv6 header
|
* @param p the input packet for which the 'packet too big' should be sent,
|
||||||
* @param mtu the maximum mtu that we can accept
|
* p->payload pointing to the IPv6 header
|
||||||
*/
|
* @param mtu the maximum mtu that we can accept
|
||||||
void
|
*/
|
||||||
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
void
|
||||||
{
|
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
||||||
icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
|
{
|
||||||
}
|
icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Send an icmpv6 'time exceeded' packet.
|
/**
|
||||||
*
|
* Send an icmpv6 'time exceeded' packet.
|
||||||
* @param p the input packet for which the 'unreachable' should be sent,
|
*
|
||||||
* p->payload pointing to the IPv6 header
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
* @param c ICMPv6 code for the time exceeded type
|
* p->payload pointing to the IPv6 header
|
||||||
*/
|
* @param c ICMPv6 code for the time exceeded type
|
||||||
void
|
*/
|
||||||
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
void
|
||||||
{
|
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
||||||
icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
|
{
|
||||||
}
|
icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Send an icmpv6 'parameter problem' packet.
|
/**
|
||||||
*
|
* Send an icmpv6 'parameter problem' packet.
|
||||||
* @param p the input packet for which the 'param problem' should be sent,
|
*
|
||||||
* p->payload pointing to the IP header
|
* @param p the input packet for which the 'param problem' should be sent,
|
||||||
* @param c ICMPv6 code for the param problem type
|
* p->payload pointing to the IP header
|
||||||
* @param pointer the pointer to the byte where the parameter is found
|
* @param c ICMPv6 code for the param problem type
|
||||||
*/
|
* @param pointer the pointer to the byte where the parameter is found
|
||||||
void
|
*/
|
||||||
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
void
|
||||||
{
|
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
||||||
icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
|
{
|
||||||
}
|
icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Send an ICMPv6 packet in response to an incoming packet.
|
/**
|
||||||
*
|
* Send an ICMPv6 packet in response to an incoming packet.
|
||||||
* @param p the input packet for which the response should be sent,
|
*
|
||||||
* p->payload pointing to the IPv6 header
|
* @param p the input packet for which the response should be sent,
|
||||||
* @param code Code of the ICMPv6 header
|
* p->payload pointing to the IPv6 header
|
||||||
* @param data Additional 32-bit parameter in the ICMPv6 header
|
* @param code Code of the ICMPv6 header
|
||||||
* @param type Type of the ICMPv6 header
|
* @param data Additional 32-bit parameter in the ICMPv6 header
|
||||||
*/
|
* @param type Type of the ICMPv6 header
|
||||||
static void
|
*/
|
||||||
icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
|
static void
|
||||||
{
|
icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
|
||||||
struct pbuf *q;
|
{
|
||||||
struct icmp6_hdr *icmp6hdr;
|
struct pbuf *q;
|
||||||
const ip6_addr_t *reply_src;
|
struct icmp6_hdr *icmp6hdr;
|
||||||
ip6_addr_t *reply_dest;
|
const ip6_addr_t *reply_src;
|
||||||
ip6_addr_t reply_src_local, reply_dest_local;
|
ip6_addr_t *reply_dest;
|
||||||
struct ip6_hdr *ip6hdr;
|
ip6_addr_t reply_src_local, reply_dest_local;
|
||||||
struct netif *netif;
|
struct ip6_hdr *ip6hdr;
|
||||||
|
struct netif *netif;
|
||||||
/* ICMPv6 header + IPv6 header + data */
|
|
||||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
|
/* ICMPv6 header + IPv6 header + data */
|
||||||
PBUF_RAM);
|
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
|
||||||
if (q == NULL) {
|
PBUF_RAM);
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
if (q == NULL) {
|
||||||
ICMP6_STATS_INC(icmp6.memerr);
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.memerr);
|
||||||
}
|
return;
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
|
}
|
||||||
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
|
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
|
||||||
|
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
|
||||||
icmp6hdr = (struct icmp6_hdr *)q->payload;
|
|
||||||
icmp6hdr->type = type;
|
icmp6hdr = (struct icmp6_hdr *)q->payload;
|
||||||
icmp6hdr->code = code;
|
icmp6hdr->type = type;
|
||||||
icmp6hdr->data = data;
|
icmp6hdr->code = code;
|
||||||
|
icmp6hdr->data = data;
|
||||||
/* copy fields from original packet */
|
|
||||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
|
/* copy fields from original packet */
|
||||||
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
|
||||||
|
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
||||||
/* Get the destination address and netif for this ICMP message. */
|
|
||||||
if ((ip_current_netif() == NULL) ||
|
/* Get the destination address and netif for this ICMP message. */
|
||||||
((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) {
|
if ((ip_current_netif() == NULL) ||
|
||||||
/* Special case, as ip6_current_xxx is either NULL, or points
|
((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) {
|
||||||
* to a different packet than the one that expired.
|
/* Special case, as ip6_current_xxx is either NULL, or points
|
||||||
* We must use the addresses that are stored in the expired packet. */
|
* to a different packet than the one that expired.
|
||||||
ip6hdr = (struct ip6_hdr *)p->payload;
|
* We must use the addresses that are stored in the expired packet. */
|
||||||
/* copy from packed address to aligned address */
|
ip6hdr = (struct ip6_hdr *)p->payload;
|
||||||
ip6_addr_copy(reply_dest_local, ip6hdr->src);
|
/* copy from packed address to aligned address */
|
||||||
ip6_addr_copy(reply_src_local, ip6hdr->dest);
|
ip6_addr_copy(reply_dest_local, ip6hdr->src);
|
||||||
reply_dest = &reply_dest_local;
|
ip6_addr_copy(reply_src_local, ip6hdr->dest);
|
||||||
reply_src = &reply_src_local;
|
reply_dest = &reply_dest_local;
|
||||||
netif = ip6_route(reply_src, reply_dest);
|
reply_src = &reply_src_local;
|
||||||
if (netif == NULL) {
|
netif = ip6_route(reply_src, reply_dest);
|
||||||
/* drop */
|
if (netif == NULL) {
|
||||||
pbuf_free(q);
|
/* drop */
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
pbuf_free(q);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.rterr);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
netif = ip_current_netif();
|
else {
|
||||||
reply_dest = ip6_current_src_addr();
|
netif = ip_current_netif();
|
||||||
|
reply_dest = ip6_current_src_addr();
|
||||||
/* Select an address to use as source. */
|
|
||||||
reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest));
|
/* Select an address to use as source. */
|
||||||
if (reply_src == NULL) {
|
reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest));
|
||||||
/* drop */
|
if (reply_src == NULL) {
|
||||||
pbuf_free(q);
|
/* drop */
|
||||||
ICMP6_STATS_INC(icmp6.rterr);
|
pbuf_free(q);
|
||||||
return;
|
ICMP6_STATS_INC(icmp6.rterr);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* calculate checksum */
|
|
||||||
icmp6hdr->chksum = 0;
|
/* calculate checksum */
|
||||||
#if CHECKSUM_GEN_ICMP6
|
icmp6hdr->chksum = 0;
|
||||||
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
#if CHECKSUM_GEN_ICMP6
|
||||||
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
|
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
|
||||||
reply_src, reply_dest);
|
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
|
||||||
}
|
reply_src, reply_dest);
|
||||||
#endif /* CHECKSUM_GEN_ICMP6 */
|
}
|
||||||
|
#endif /* CHECKSUM_GEN_ICMP6 */
|
||||||
ICMP6_STATS_INC(icmp6.xmit);
|
|
||||||
ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
|
ICMP6_STATS_INC(icmp6.xmit);
|
||||||
pbuf_free(q);
|
ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
|
||||||
}
|
pbuf_free(q);
|
||||||
|
}
|
||||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
|
||||||
|
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||||
|
|||||||
106
ext/lwip/src/core/ipv6/inet6.c
Normal file → Executable file
106
ext/lwip/src/core/ipv6/inet6.c
Normal file → Executable file
@@ -1,53 +1,53 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* INET v6 addresses.
|
* INET v6 addresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
* <delamer@inicotech.com>
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
/** This variable is initialized by the system to contain the wildcard IPv6 address.
|
/** This variable is initialized by the system to contain the wildcard IPv6 address.
|
||||||
*/
|
*/
|
||||||
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
|||||||
2230
ext/lwip/src/core/ipv6/ip6.c
Normal file → Executable file
2230
ext/lwip/src/core/ipv6/ip6.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
584
ext/lwip/src/core/ipv6/ip6_addr.c
Normal file → Executable file
584
ext/lwip/src/core/ipv6/ip6_addr.c
Normal file → Executable file
@@ -1,292 +1,292 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* IPv6 addresses.
|
* IPv6 addresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
* Functions for handling IPv6 addresses.
|
* Functions for handling IPv6 addresses.
|
||||||
*
|
*
|
||||||
* Please coordinate changes and requests with Ivan Delamer
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
* <delamer@inicotech.com>
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
|
|
||||||
/* used by IP6_ADDR_ANY(6) in ip6_addr.h */
|
/* used by IP6_ADDR_ANY(6) in ip6_addr.h */
|
||||||
const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul);
|
const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul);
|
||||||
|
|
||||||
#ifndef isprint
|
#ifndef isprint
|
||||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||||
#define isdigit(c) in_range(c, '0', '9')
|
#define isdigit(c) in_range(c, '0', '9')
|
||||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||||
#define islower(c) in_range(c, 'a', 'z')
|
#define islower(c) in_range(c, 'a', 'z')
|
||||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||||
#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
|
#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether "cp" is a valid ascii representation
|
* Check whether "cp" is a valid ascii representation
|
||||||
* of an IPv6 address and convert to a binary address.
|
* of an IPv6 address and convert to a binary address.
|
||||||
* Returns 1 if the address is valid, 0 if not.
|
* Returns 1 if the address is valid, 0 if not.
|
||||||
*
|
*
|
||||||
* @param cp IPv6 address in ascii representation (e.g. "FF01::1")
|
* @param cp IPv6 address in ascii representation (e.g. "FF01::1")
|
||||||
* @param addr pointer to which to save the ip address in network order
|
* @param addr pointer to which to save the ip address in network order
|
||||||
* @return 1 if cp could be converted to addr, 0 on failure
|
* @return 1 if cp could be converted to addr, 0 on failure
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
||||||
{
|
{
|
||||||
u32_t addr_index, zero_blocks, current_block_index, current_block_value;
|
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
|
/* Count the number of colons, to count the number of blocks in a "::" sequence
|
||||||
zero_blocks may be 1 even if there are no :: sequences */
|
zero_blocks may be 1 even if there are no :: sequences */
|
||||||
zero_blocks = 8;
|
zero_blocks = 8;
|
||||||
for (s = cp; *s != 0; s++) {
|
for (s = cp; *s != 0; s++) {
|
||||||
if (*s == ':') {
|
if (*s == ':') {
|
||||||
zero_blocks--;
|
zero_blocks--;
|
||||||
} else if (!isxdigit(*s)) {
|
} else if (!isxdigit(*s)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse each block */
|
/* parse each block */
|
||||||
addr_index = 0;
|
addr_index = 0;
|
||||||
current_block_index = 0;
|
current_block_index = 0;
|
||||||
current_block_value = 0;
|
current_block_value = 0;
|
||||||
for (s = cp; *s != 0; s++) {
|
for (s = cp; *s != 0; s++) {
|
||||||
if (*s == ':') {
|
if (*s == ':') {
|
||||||
if (addr) {
|
if (addr) {
|
||||||
if (current_block_index & 0x1) {
|
if (current_block_index & 0x1) {
|
||||||
addr->addr[addr_index++] |= current_block_value;
|
addr->addr[addr_index++] |= current_block_value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr->addr[addr_index] = current_block_value << 16;
|
addr->addr[addr_index] = current_block_value << 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_block_index++;
|
current_block_index++;
|
||||||
current_block_value = 0;
|
current_block_value = 0;
|
||||||
if (current_block_index > 7) {
|
if (current_block_index > 7) {
|
||||||
/* address too long! */
|
/* address too long! */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (s[1] == ':') {
|
if (s[1] == ':') {
|
||||||
if (s[2] == ':') {
|
if (s[2] == ':') {
|
||||||
/* invalid format: three successive colons */
|
/* invalid format: three successive colons */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
/* "::" found, set zeros */
|
/* "::" found, set zeros */
|
||||||
while (zero_blocks > 0) {
|
while (zero_blocks > 0) {
|
||||||
zero_blocks--;
|
zero_blocks--;
|
||||||
if (current_block_index & 0x1) {
|
if (current_block_index & 0x1) {
|
||||||
addr_index++;
|
addr_index++;
|
||||||
} else {
|
} else {
|
||||||
if (addr) {
|
if (addr) {
|
||||||
addr->addr[addr_index] = 0;
|
addr->addr[addr_index] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_block_index++;
|
current_block_index++;
|
||||||
if (current_block_index > 7) {
|
if (current_block_index > 7) {
|
||||||
/* address too long! */
|
/* address too long! */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isxdigit(*s)) {
|
} else if (isxdigit(*s)) {
|
||||||
/* add current digit */
|
/* add current digit */
|
||||||
current_block_value = (current_block_value << 4) +
|
current_block_value = (current_block_value << 4) +
|
||||||
(isdigit(*s) ? *s - '0' :
|
(isdigit(*s) ? (u32_t)(*s - '0') :
|
||||||
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
|
(u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
|
||||||
} else {
|
} else {
|
||||||
/* unexpected digit, space? CRLF? */
|
/* unexpected digit, space? CRLF? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
if (current_block_index & 0x1) {
|
if (current_block_index & 0x1) {
|
||||||
addr->addr[addr_index++] |= current_block_value;
|
addr->addr[addr_index++] |= current_block_value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr->addr[addr_index] = current_block_value << 16;
|
addr->addr[addr_index] = current_block_value << 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert to network byte order. */
|
/* convert to network byte order. */
|
||||||
if (addr) {
|
if (addr) {
|
||||||
for (addr_index = 0; addr_index < 4; addr_index++) {
|
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_block_index != 7) {
|
if (current_block_index != 7) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert numeric IPv6 address into ASCII representation.
|
* Convert numeric IPv6 address into ASCII representation.
|
||||||
* returns ptr to static buffer; not reentrant!
|
* returns ptr to static buffer; not reentrant!
|
||||||
*
|
*
|
||||||
* @param addr ip6 address in network order to convert
|
* @param addr ip6 address in network order to convert
|
||||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||||
* representation of addr
|
* representation of addr
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
ip6addr_ntoa(const ip6_addr_t *addr)
|
ip6addr_ntoa(const ip6_addr_t *addr)
|
||||||
{
|
{
|
||||||
static char str[40];
|
static char str[40];
|
||||||
return ip6addr_ntoa_r(addr, str, 40);
|
return ip6addr_ntoa_r(addr, str, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
||||||
*
|
*
|
||||||
* @param addr ip6 address in network order to convert
|
* @param addr ip6 address in network order to convert
|
||||||
* @param buf target buffer where the string is stored
|
* @param buf target buffer where the string is stored
|
||||||
* @param buflen length of buf
|
* @param buflen length of buf
|
||||||
* @return either pointer to buf which now holds the ASCII
|
* @return either pointer to buf which now holds the ASCII
|
||||||
* representation of addr or NULL if buf was too small
|
* representation of addr or NULL if buf was too small
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
u32_t current_block_index, current_block_value, next_block_value;
|
u32_t current_block_index, current_block_value, next_block_value;
|
||||||
s32_t i;
|
s32_t i;
|
||||||
u8_t zero_flag, empty_block_flag;
|
u8_t zero_flag, empty_block_flag;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
empty_block_flag = 0; /* used to indicate a zero chain for "::' */
|
empty_block_flag = 0; /* used to indicate a zero chain for "::' */
|
||||||
|
|
||||||
for (current_block_index = 0; current_block_index < 8; current_block_index++) {
|
for (current_block_index = 0; current_block_index < 8; current_block_index++) {
|
||||||
/* get the current 16-bit block */
|
/* 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) {
|
if ((current_block_index & 0x1) == 0) {
|
||||||
current_block_value = current_block_value >> 16;
|
current_block_value = current_block_value >> 16;
|
||||||
}
|
}
|
||||||
current_block_value &= 0xffff;
|
current_block_value &= 0xffff;
|
||||||
|
|
||||||
/* Check for empty block. */
|
/* Check for empty block. */
|
||||||
if (current_block_value == 0) {
|
if (current_block_value == 0) {
|
||||||
if (current_block_index == 7 && empty_block_flag == 1) {
|
if (current_block_index == 7 && empty_block_flag == 1) {
|
||||||
/* special case, we must render a ':' for the last block. */
|
/* special case, we must render a ':' for the last block. */
|
||||||
buf[i++] = ':';
|
buf[i++] = ':';
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (empty_block_flag == 0) {
|
if (empty_block_flag == 0) {
|
||||||
/* generate empty block "::", but only if more than one contiguous zero block,
|
/* generate empty block "::", but only if more than one contiguous zero block,
|
||||||
* according to current formatting suggestions RFC 5952. */
|
* 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) {
|
if ((current_block_index & 0x1) == 0x01) {
|
||||||
next_block_value = next_block_value >> 16;
|
next_block_value = next_block_value >> 16;
|
||||||
}
|
}
|
||||||
next_block_value &= 0xffff;
|
next_block_value &= 0xffff;
|
||||||
if (next_block_value == 0) {
|
if (next_block_value == 0) {
|
||||||
empty_block_flag = 1;
|
empty_block_flag = 1;
|
||||||
buf[i++] = ':';
|
buf[i++] = ':';
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
continue; /* move on to next block. */
|
continue; /* move on to next block. */
|
||||||
}
|
}
|
||||||
} else if (empty_block_flag == 1) {
|
} else if (empty_block_flag == 1) {
|
||||||
/* move on to next block. */
|
/* move on to next block. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (empty_block_flag == 1) {
|
} else if (empty_block_flag == 1) {
|
||||||
/* Set this flag value so we don't produce multiple empty blocks. */
|
/* Set this flag value so we don't produce multiple empty blocks. */
|
||||||
empty_block_flag = 2;
|
empty_block_flag = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_block_index > 0) {
|
if (current_block_index > 0) {
|
||||||
buf[i++] = ':';
|
buf[i++] = ':';
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((current_block_value & 0xf000) == 0) {
|
if ((current_block_value & 0xf000) == 0) {
|
||||||
zero_flag = 1;
|
zero_flag = 1;
|
||||||
} else {
|
} else {
|
||||||
buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
|
buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
|
||||||
zero_flag = 0;
|
zero_flag = 0;
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
|
if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
} else {
|
} else {
|
||||||
buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
|
buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
|
||||||
zero_flag = 0;
|
zero_flag = 0;
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
|
if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
|
buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
|
||||||
zero_flag = 0;
|
zero_flag = 0;
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[i++] = xchar((current_block_value & 0xf));
|
buf[i++] = xchar((current_block_value & 0xf));
|
||||||
if (i >= buflen) {
|
if (i >= buflen) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
|||||||
1581
ext/lwip/src/core/ipv6/ip6_frag.c
Normal file → Executable file
1581
ext/lwip/src/core/ipv6/ip6_frag.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1186
ext/lwip/src/core/ipv6/mld6.c
Normal file → Executable file
1186
ext/lwip/src/core/ipv6/mld6.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
3986
ext/lwip/src/core/ipv6/nd6.c
Normal file → Executable file
3986
ext/lwip/src/core/ipv6/nd6.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1554
ext/lwip/src/core/mem.c
Normal file → Executable file
1554
ext/lwip/src/core/mem.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
997
ext/lwip/src/core/memp.c
Normal file → Executable file
997
ext/lwip/src/core/memp.c
Normal file → Executable file
@@ -1,501 +1,496 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Dynamic pool memory manager
|
* Dynamic pool memory manager
|
||||||
*
|
*
|
||||||
* lwIP has dedicated pools for many structures (netconn, protocol control blocks,
|
* lwIP has dedicated pools for many structures (netconn, protocol control blocks,
|
||||||
* packet buffers, ...). All these pools are managed here.
|
* packet buffers, ...). All these pools are managed here.
|
||||||
*/
|
*
|
||||||
|
* @defgroup mempool Memory pools
|
||||||
/*
|
* @ingroup infrastructure
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Custom memory pools
|
||||||
* All rights reserved.
|
|
||||||
*
|
*/
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
/*
|
||||||
*
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* All rights reserved.
|
||||||
* this list of conditions and the following disclaimer.
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* are permitted provided that the following conditions are met:
|
||||||
* and/or other materials provided with the distribution.
|
*
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* derived from this software without specific prior written permission.
|
* this list of conditions and the following disclaimer.
|
||||||
*
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* and/or other materials provided with the distribution.
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* derived from this software without specific prior written permission.
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
*
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* OF SUCH DAMAGE.
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
*
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
*
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* 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.
|
||||||
/**
|
*
|
||||||
* @defgroup mempool Memory pools
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
* @ingroup infrastructure
|
*
|
||||||
* Custom memory pools
|
*/
|
||||||
*/
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
#include "lwip/memp.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/sys.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/stats.h"
|
|
||||||
|
#include <string.h>
|
||||||
#include <string.h>
|
|
||||||
|
/* Make sure we include everything we need for size calculation required by memp_std.h */
|
||||||
/* Make sure we include everything we need for size calculation required by memp_std.h */
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/raw.h"
|
||||||
#include "lwip/raw.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/priv/tcp_priv.h"
|
||||||
#include "lwip/priv/tcp_priv.h"
|
#include "lwip/ip4_frag.h"
|
||||||
#include "lwip/ip4_frag.h"
|
#include "lwip/netbuf.h"
|
||||||
#include "lwip/netbuf.h"
|
#include "lwip/api.h"
|
||||||
#include "lwip/api.h"
|
#include "lwip/priv/tcpip_priv.h"
|
||||||
#include "lwip/priv/tcpip_priv.h"
|
#include "lwip/priv/api_msg.h"
|
||||||
#include "lwip/priv/api_msg.h"
|
#include "lwip/sockets.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/netifapi.h"
|
||||||
#include "lwip/netifapi.h"
|
#include "lwip/etharp.h"
|
||||||
#include "lwip/etharp.h"
|
#include "lwip/igmp.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/timeouts.h"
|
||||||
#include "lwip/timeouts.h"
|
/* needed by default MEMP_NUM_SYS_TIMEOUT */
|
||||||
/* needed by default MEMP_NUM_SYS_TIMEOUT */
|
#include "netif/ppp/ppp_opts.h"
|
||||||
#include "netif/ppp/ppp_opts.h"
|
#include "lwip/netdb.h"
|
||||||
#include "lwip/netdb.h"
|
#include "lwip/dns.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/priv/nd6_priv.h"
|
||||||
#include "lwip/nd6.h"
|
#include "lwip/ip6_frag.h"
|
||||||
#include "lwip/ip6_frag.h"
|
#include "lwip/mld6.h"
|
||||||
#include "lwip/mld6.h"
|
|
||||||
|
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
|
||||||
|
#include "lwip/priv/memp_std.h"
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
|
|
||||||
#include "lwip/priv/memp_std.h"
|
const struct memp_desc* const memp_pools[MEMP_MAX] = {
|
||||||
|
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
|
||||||
const struct memp_desc* const memp_pools[MEMP_MAX] = {
|
#include "lwip/priv/memp_std.h"
|
||||||
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
|
};
|
||||||
#include "lwip/priv/memp_std.h"
|
|
||||||
};
|
#ifdef LWIP_HOOK_FILENAME
|
||||||
|
#include LWIP_HOOK_FILENAME
|
||||||
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
|
#endif
|
||||||
#undef MEMP_OVERFLOW_CHECK
|
|
||||||
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
|
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
|
||||||
#define MEMP_OVERFLOW_CHECK 1
|
#undef MEMP_OVERFLOW_CHECK
|
||||||
#endif
|
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
|
||||||
|
#define MEMP_OVERFLOW_CHECK 1
|
||||||
#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
|
#endif
|
||||||
/**
|
|
||||||
* Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
|
#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
|
||||||
*/
|
/**
|
||||||
static int
|
* Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
|
||||||
memp_sanity(const struct memp_desc *desc)
|
*/
|
||||||
{
|
static int
|
||||||
struct memp *t, *h;
|
memp_sanity(const struct memp_desc *desc)
|
||||||
|
{
|
||||||
t = *desc->tab;
|
struct memp *t, *h;
|
||||||
if (t != NULL) {
|
|
||||||
for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
|
t = *desc->tab;
|
||||||
h = ((h->next != NULL) ? h->next->next : NULL)) {
|
if (t != NULL) {
|
||||||
if (t == h) {
|
for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
|
||||||
return 0;
|
h = ((h->next != NULL) ? h->next->next : NULL)) {
|
||||||
}
|
if (t == h) {
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
|
return 1;
|
||||||
|
}
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
|
||||||
/**
|
|
||||||
* Check if a memp element was victim of an overflow
|
#if MEMP_OVERFLOW_CHECK
|
||||||
* (e.g. the restricted area after it has been altered)
|
/**
|
||||||
*
|
* Check if a memp element was victim of an overflow
|
||||||
* @param p the memp element to check
|
* (e.g. the restricted area after it has been altered)
|
||||||
* @param memp_type the pool p comes from
|
*
|
||||||
*/
|
* @param p the memp element to check
|
||||||
static void
|
* @param desc the pool p comes from
|
||||||
memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc)
|
*/
|
||||||
{
|
static void
|
||||||
u16_t k;
|
memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc)
|
||||||
u8_t *m;
|
{
|
||||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||||
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
u16_t k;
|
||||||
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
u8_t *m;
|
||||||
if (m[k] != 0xcd) {
|
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
||||||
char errstr[128] = "detected memp overflow in pool ";
|
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
||||||
strcat(errstr, desc->desc);
|
if (m[k] != 0xcd) {
|
||||||
LWIP_ASSERT(errstr, 0);
|
char errstr[128] = "detected memp overflow in pool ";
|
||||||
}
|
strcat(errstr, desc->desc);
|
||||||
}
|
LWIP_ASSERT(errstr, 0);
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||||
/**
|
LWIP_UNUSED_ARG(p);
|
||||||
* Check if a memp element was victim of an underflow
|
LWIP_UNUSED_ARG(desc);
|
||||||
* (e.g. the restricted area before it has been altered)
|
#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||||
*
|
}
|
||||||
* @param p the memp element to check
|
|
||||||
* @param memp_type the pool p comes from
|
/**
|
||||||
*/
|
* Check if a memp element was victim of an underflow
|
||||||
static void
|
* (e.g. the restricted area before it has been altered)
|
||||||
memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc)
|
*
|
||||||
{
|
* @param p the memp element to check
|
||||||
u16_t k;
|
* @param desc the pool p comes from
|
||||||
u8_t *m;
|
*/
|
||||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
static void
|
||||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc)
|
||||||
for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
|
{
|
||||||
if (m[k] != 0xcd) {
|
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
||||||
char errstr[128] = "detected memp underflow in pool ";
|
u16_t k;
|
||||||
strcat(errstr, desc->desc);
|
u8_t *m;
|
||||||
LWIP_ASSERT(errstr, 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) {
|
||||||
#endif
|
char errstr[128] = "detected memp underflow in pool ";
|
||||||
}
|
strcat(errstr, desc->desc);
|
||||||
|
LWIP_ASSERT(errstr, 0);
|
||||||
/**
|
}
|
||||||
* Initialize the restricted area of on memp element.
|
}
|
||||||
*/
|
#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
|
||||||
static void
|
LWIP_UNUSED_ARG(p);
|
||||||
memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
|
LWIP_UNUSED_ARG(desc);
|
||||||
{
|
#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
|
||||||
u8_t *m;
|
}
|
||||||
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
|
||||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
/**
|
||||||
memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
|
* Initialize the restricted area of on memp element.
|
||||||
#endif
|
*/
|
||||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
static void
|
||||||
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
|
||||||
memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
|
{
|
||||||
#endif
|
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||||
}
|
u8_t *m;
|
||||||
|
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
||||||
/**
|
memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
|
||||||
* Do an overflow check for all elements in every pool.
|
#endif
|
||||||
*
|
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||||
* @see memp_overflow_check_element for a description of the check
|
m = (u8_t*)p + MEMP_SIZE + desc->size;
|
||||||
*/
|
memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||||
static void
|
#endif
|
||||||
memp_overflow_check_all(void)
|
#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||||
{
|
LWIP_UNUSED_ARG(p);
|
||||||
u16_t i, j;
|
LWIP_UNUSED_ARG(desc);
|
||||||
struct memp *p;
|
#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
}
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
|
#if MEMP_OVERFLOW_CHECK >= 2
|
||||||
for (i = 0; i < MEMP_MAX; ++i) {
|
/**
|
||||||
p = (struct memp *)(size_t)(memp_pools[i]->base);
|
* Do an overflow check for all elements in every pool.
|
||||||
for (j = 0; j < memp_pools[i]->num; ++j) {
|
*
|
||||||
memp_overflow_check_element_overflow(p, memp_pools[i]);
|
* @see memp_overflow_check_element for a description of the check
|
||||||
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);
|
static void
|
||||||
}
|
memp_overflow_check_all(void)
|
||||||
}
|
{
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
u16_t i, j;
|
||||||
}
|
struct memp *p;
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
SYS_ARCH_DECL_PROTECT(old_level);
|
||||||
|
SYS_ARCH_PROTECT(old_level);
|
||||||
#if !MEMP_MEM_MALLOC
|
|
||||||
/**
|
for (i = 0; i < MEMP_MAX; ++i) {
|
||||||
* Initialize the restricted areas of all memp elements in a pool.
|
p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base);
|
||||||
*/
|
for (j = 0; j < memp_pools[i]->num; ++j) {
|
||||||
static void
|
memp_overflow_check_element_overflow(p, memp_pools[i]);
|
||||||
memp_overflow_init(const struct memp_desc *desc)
|
memp_overflow_check_element_underflow(p, memp_pools[i]);
|
||||||
{
|
p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
|
||||||
u16_t i;
|
}
|
||||||
struct memp *p;
|
}
|
||||||
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
p = (struct memp *)(size_t)(desc->base);
|
}
|
||||||
for (i = 0; i < desc->num; ++i) {
|
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||||
memp_overflow_init_element(p, desc);
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
|
||||||
}
|
/**
|
||||||
}
|
* Initialize custom memory pool.
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
* Related functions: memp_malloc_pool, memp_free_pool
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
*
|
||||||
|
* @param desc pool to initialize
|
||||||
/**
|
*/
|
||||||
* Initialize custom memory pool.
|
void
|
||||||
* Related functions: memp_malloc_pool, memp_free_pool
|
memp_init_pool(const struct memp_desc *desc)
|
||||||
*
|
{
|
||||||
* @param desc pool to initialize
|
#if MEMP_MEM_MALLOC
|
||||||
*/
|
LWIP_UNUSED_ARG(desc);
|
||||||
void
|
#else
|
||||||
memp_init_pool(const struct memp_desc *desc)
|
int i;
|
||||||
{
|
struct memp *memp;
|
||||||
#if MEMP_MEM_MALLOC
|
|
||||||
LWIP_UNUSED_ARG(desc);
|
*desc->tab = NULL;
|
||||||
#else
|
memp = (struct memp*)LWIP_MEM_ALIGN(desc->base);
|
||||||
int i;
|
/* create a linked list of memp elements */
|
||||||
struct memp *memp;
|
for (i = 0; i < desc->num; ++i) {
|
||||||
|
memp->next = *desc->tab;
|
||||||
*desc->tab = NULL;
|
*desc->tab = memp;
|
||||||
memp = (struct memp*)LWIP_MEM_ALIGN(desc->base);
|
#if MEMP_OVERFLOW_CHECK
|
||||||
/* create a linked list of memp elements */
|
memp_overflow_init_element(memp, desc);
|
||||||
for (i = 0; i < desc->num; ++i) {
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
memp->next = *desc->tab;
|
/* cast through void* to get rid of alignment warnings */
|
||||||
*desc->tab = memp;
|
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
|
||||||
/* cast through void* to get rid of alignment warnings */
|
#if MEMP_OVERFLOW_CHECK
|
||||||
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
|
+ MEMP_SANITY_REGION_AFTER_ALIGNED
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#endif
|
||||||
+ MEMP_SANITY_REGION_AFTER_ALIGNED
|
);
|
||||||
#endif
|
}
|
||||||
);
|
#if MEMP_STATS
|
||||||
}
|
desc->stats->avail = desc->num;
|
||||||
|
#endif /* MEMP_STATS */
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#endif /* !MEMP_MEM_MALLOC */
|
||||||
memp_overflow_init(desc);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
desc->stats->name = desc->desc;
|
||||||
|
#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
|
||||||
#if MEMP_STATS
|
}
|
||||||
#if !MEMP_MEM_MALLOC
|
|
||||||
desc->stats->avail = desc->num;
|
/**
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
* Initializes lwIP built-in pools.
|
||||||
|
* Related functions: memp_malloc, memp_free
|
||||||
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
|
*
|
||||||
desc->stats->name = desc->desc;
|
* Carves out memp_memory into linked lists for each pool-type.
|
||||||
#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */
|
*/
|
||||||
#endif /* MEMP_STATS */
|
void
|
||||||
}
|
memp_init(void)
|
||||||
|
{
|
||||||
/**
|
u16_t i;
|
||||||
* Initializes lwIP built-in pools.
|
|
||||||
* Related functions: memp_malloc, memp_free
|
/* for every pool: */
|
||||||
*
|
for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
|
||||||
* Carves out memp_memory into linked lists for each pool-type.
|
memp_init_pool(memp_pools[i]);
|
||||||
*/
|
|
||||||
void
|
#if LWIP_STATS && MEMP_STATS
|
||||||
memp_init(void)
|
lwip_stats.memp[i] = memp_pools[i]->stats;
|
||||||
{
|
#endif
|
||||||
u16_t i;
|
}
|
||||||
|
|
||||||
/* for every pool: */
|
#if MEMP_OVERFLOW_CHECK >= 2
|
||||||
for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
|
/* check everything a first time to see if it worked */
|
||||||
memp_init_pool(memp_pools[i]);
|
memp_overflow_check_all();
|
||||||
|
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||||
#if LWIP_STATS && MEMP_STATS
|
}
|
||||||
lwip_stats.memp[i] = memp_pools[i]->stats;
|
|
||||||
#endif
|
static void*
|
||||||
}
|
#if !MEMP_OVERFLOW_CHECK
|
||||||
|
do_memp_malloc_pool(const struct memp_desc *desc)
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
#else
|
||||||
/* check everything a first time to see if it worked */
|
do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
|
||||||
memp_overflow_check_all();
|
#endif
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
{
|
||||||
}
|
struct memp *memp;
|
||||||
|
SYS_ARCH_DECL_PROTECT(old_level);
|
||||||
static void*
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
#if MEMP_MEM_MALLOC
|
||||||
do_memp_malloc_pool(const struct memp_desc *desc)
|
memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
|
||||||
#else
|
SYS_ARCH_PROTECT(old_level);
|
||||||
do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
|
#else /* MEMP_MEM_MALLOC */
|
||||||
#endif
|
SYS_ARCH_PROTECT(old_level);
|
||||||
{
|
|
||||||
struct memp *memp;
|
memp = *desc->tab;
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
#endif /* MEMP_MEM_MALLOC */
|
||||||
|
|
||||||
#if MEMP_MEM_MALLOC
|
if (memp != NULL) {
|
||||||
memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
|
#if !MEMP_MEM_MALLOC
|
||||||
SYS_ARCH_PROTECT(old_level);
|
#if MEMP_OVERFLOW_CHECK == 1
|
||||||
#else /* MEMP_MEM_MALLOC */
|
memp_overflow_check_element_overflow(memp, desc);
|
||||||
SYS_ARCH_PROTECT(old_level);
|
memp_overflow_check_element_underflow(memp, desc);
|
||||||
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
memp = *desc->tab;
|
|
||||||
|
*desc->tab = memp->next;
|
||||||
#if MEMP_OVERFLOW_CHECK == 1
|
#if MEMP_OVERFLOW_CHECK
|
||||||
memp_overflow_check_element_overflow(memp, desc);
|
memp->next = NULL;
|
||||||
memp_overflow_check_element_underflow(memp, desc);
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
#endif /* !MEMP_MEM_MALLOC */
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
#if MEMP_OVERFLOW_CHECK
|
||||||
|
memp->file = file;
|
||||||
if (memp != NULL) {
|
memp->line = line;
|
||||||
#if !MEMP_MEM_MALLOC
|
#if MEMP_MEM_MALLOC
|
||||||
*desc->tab = memp->next;
|
memp_overflow_init_element(memp, desc);
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#endif /* MEMP_MEM_MALLOC */
|
||||||
memp->next = NULL;
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#if MEMP_STATS
|
||||||
memp->file = file;
|
desc->stats->used++;
|
||||||
memp->line = line;
|
if (desc->stats->used > desc->stats->max) {
|
||||||
#if MEMP_MEM_MALLOC
|
desc->stats->max = desc->stats->used;
|
||||||
memp_overflow_init_element(memp, desc);
|
}
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
#endif
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
/* cast through u8_t* to get rid of alignment warnings */
|
||||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
return ((u8_t*)memp + MEMP_SIZE);
|
||||||
#if MEMP_STATS
|
} else {
|
||||||
desc->stats->used++;
|
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
|
||||||
if (desc->stats->used > desc->stats->max) {
|
#if MEMP_STATS
|
||||||
desc->stats->max = desc->stats->used;
|
desc->stats->err++;
|
||||||
}
|
#endif
|
||||||
#endif
|
}
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
/* cast through u8_t* to get rid of alignment warnings */
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
return ((u8_t*)memp + MEMP_SIZE);
|
return NULL;
|
||||||
} else {
|
}
|
||||||
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
|
|
||||||
#if MEMP_STATS
|
/**
|
||||||
desc->stats->err++;
|
* Get an element from a custom pool.
|
||||||
#endif
|
*
|
||||||
}
|
* @param desc the pool to get an element from
|
||||||
|
*
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
* @return a pointer to the allocated memory or a NULL pointer on error
|
||||||
return NULL;
|
*/
|
||||||
}
|
void *
|
||||||
|
#if !MEMP_OVERFLOW_CHECK
|
||||||
/**
|
memp_malloc_pool(const struct memp_desc *desc)
|
||||||
* Get an element from a custom pool.
|
#else
|
||||||
*
|
memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
|
||||||
* @param desc the pool to get an element from
|
#endif
|
||||||
*
|
{
|
||||||
* @return a pointer to the allocated memory or a NULL pointer on error
|
LWIP_ASSERT("invalid pool desc", desc != NULL);
|
||||||
*/
|
if (desc == NULL) {
|
||||||
void *
|
return NULL;
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
}
|
||||||
memp_malloc_pool(const struct memp_desc *desc)
|
|
||||||
#else
|
#if !MEMP_OVERFLOW_CHECK
|
||||||
memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
|
return do_memp_malloc_pool(desc);
|
||||||
#endif
|
#else
|
||||||
{
|
return do_memp_malloc_pool_fn(desc, file, line);
|
||||||
LWIP_ASSERT("invalid pool desc", desc != NULL);
|
#endif
|
||||||
if (desc == NULL) {
|
}
|
||||||
return NULL;
|
|
||||||
}
|
/**
|
||||||
|
* Get an element from a specific pool.
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
*
|
||||||
return do_memp_malloc_pool(desc);
|
* @param type the pool to get an element from
|
||||||
#else
|
*
|
||||||
return do_memp_malloc_pool_fn(desc, file, line);
|
* @return a pointer to the allocated memory or a NULL pointer on error
|
||||||
#endif
|
*/
|
||||||
}
|
void *
|
||||||
|
#if !MEMP_OVERFLOW_CHECK
|
||||||
/**
|
memp_malloc(memp_t type)
|
||||||
* Get an element from a specific pool.
|
#else
|
||||||
*
|
memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||||
* @param type the pool to get an element from
|
#endif
|
||||||
*
|
{
|
||||||
* @return a pointer to the allocated memory or a NULL pointer on error
|
void *memp;
|
||||||
*/
|
LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
|
||||||
void *
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
#if MEMP_OVERFLOW_CHECK >= 2
|
||||||
memp_malloc(memp_t type)
|
memp_overflow_check_all();
|
||||||
#else
|
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||||
memp_malloc_fn(memp_t type, const char* file, const int line)
|
|
||||||
#endif
|
#if !MEMP_OVERFLOW_CHECK
|
||||||
{
|
memp = do_memp_malloc_pool(memp_pools[type]);
|
||||||
void *memp;
|
#else
|
||||||
LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
|
memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
|
||||||
|
#endif
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
|
||||||
memp_overflow_check_all();
|
return memp;
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
}
|
||||||
|
|
||||||
#if !MEMP_OVERFLOW_CHECK
|
static void
|
||||||
memp = do_memp_malloc_pool(memp_pools[type]);
|
do_memp_free_pool(const struct memp_desc* desc, void *mem)
|
||||||
#else
|
{
|
||||||
memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
|
struct memp *memp;
|
||||||
#endif
|
SYS_ARCH_DECL_PROTECT(old_level);
|
||||||
|
|
||||||
return memp;
|
LWIP_ASSERT("memp_free: mem properly aligned",
|
||||||
}
|
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
|
||||||
|
|
||||||
static void
|
/* cast through void* to get rid of alignment warnings */
|
||||||
do_memp_free_pool(const struct memp_desc* desc, void *mem)
|
memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
|
||||||
{
|
|
||||||
struct memp *memp;
|
SYS_ARCH_PROTECT(old_level);
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
#if MEMP_OVERFLOW_CHECK == 1
|
||||||
LWIP_ASSERT("memp_free: mem properly aligned",
|
memp_overflow_check_element_overflow(memp, desc);
|
||||||
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
|
memp_overflow_check_element_underflow(memp, desc);
|
||||||
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
/* cast through void* to get rid of alignment warnings */
|
|
||||||
memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
|
#if MEMP_STATS
|
||||||
|
desc->stats->used--;
|
||||||
SYS_ARCH_PROTECT(old_level);
|
#endif
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK == 1
|
#if MEMP_MEM_MALLOC
|
||||||
memp_overflow_check_element_overflow(memp, desc);
|
LWIP_UNUSED_ARG(desc);
|
||||||
memp_overflow_check_element_underflow(memp, desc);
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
mem_free(memp);
|
||||||
|
#else /* MEMP_MEM_MALLOC */
|
||||||
#if MEMP_STATS
|
memp->next = *desc->tab;
|
||||||
desc->stats->used--;
|
*desc->tab = memp;
|
||||||
#endif
|
|
||||||
|
#if MEMP_SANITY_CHECK
|
||||||
#if MEMP_MEM_MALLOC
|
LWIP_ASSERT("memp sanity", memp_sanity(desc));
|
||||||
LWIP_UNUSED_ARG(desc);
|
#endif /* MEMP_SANITY_CHECK */
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
mem_free(memp);
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
#else /* MEMP_MEM_MALLOC */
|
#endif /* !MEMP_MEM_MALLOC */
|
||||||
memp->next = *desc->tab;
|
}
|
||||||
*desc->tab = memp;
|
|
||||||
|
/**
|
||||||
#if MEMP_SANITY_CHECK
|
* Put a custom pool element back into its pool.
|
||||||
LWIP_ASSERT("memp sanity", memp_sanity(desc));
|
*
|
||||||
#endif /* MEMP_SANITY_CHECK */
|
* @param desc the pool where to put mem
|
||||||
|
* @param mem the memp element to free
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
*/
|
||||||
#endif /* !MEMP_MEM_MALLOC */
|
void
|
||||||
}
|
memp_free_pool(const struct memp_desc* desc, void *mem)
|
||||||
|
{
|
||||||
/**
|
LWIP_ASSERT("invalid pool desc", desc != NULL);
|
||||||
* Put a custom pool element back into its pool.
|
if ((desc == NULL) || (mem == NULL)) {
|
||||||
*
|
return;
|
||||||
* @param desc the pool where to put mem
|
}
|
||||||
* @param mem the memp element to free
|
|
||||||
*/
|
do_memp_free_pool(desc, mem);
|
||||||
void
|
}
|
||||||
memp_free_pool(const struct memp_desc* desc, void *mem)
|
|
||||||
{
|
/**
|
||||||
LWIP_ASSERT("invalid pool desc", desc != NULL);
|
* Put an element back into its pool.
|
||||||
if ((desc == NULL) || (mem == NULL)) {
|
*
|
||||||
return;
|
* @param type the pool where to put mem
|
||||||
}
|
* @param mem the memp element to free
|
||||||
|
*/
|
||||||
do_memp_free_pool(desc, mem);
|
void
|
||||||
}
|
memp_free(memp_t type, void *mem)
|
||||||
|
{
|
||||||
/**
|
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
||||||
* Put an element back into its pool.
|
struct memp *old_first;
|
||||||
*
|
#endif
|
||||||
* @param type the pool where to put mem
|
|
||||||
* @param mem the memp element to free
|
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
|
||||||
*/
|
|
||||||
void
|
if (mem == NULL) {
|
||||||
memp_free(memp_t type, void *mem)
|
return;
|
||||||
{
|
}
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
struct memp *old_first;
|
#if MEMP_OVERFLOW_CHECK >= 2
|
||||||
#endif
|
memp_overflow_check_all();
|
||||||
|
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||||
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
|
|
||||||
|
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
||||||
#if MEMP_OVERFLOW_CHECK >= 2
|
old_first = *memp_pools[type]->tab;
|
||||||
memp_overflow_check_all();
|
#endif
|
||||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
|
||||||
|
do_memp_free_pool(memp_pools[type], mem);
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
|
||||||
old_first = memp_pools[type].tab;
|
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
||||||
#endif
|
if (old_first == NULL) {
|
||||||
|
LWIP_HOOK_MEMP_AVAILABLE(type);
|
||||||
do_memp_free_pool(memp_pools[type], mem);
|
}
|
||||||
|
#endif
|
||||||
#ifdef LWIP_HOOK_MEMP_AVAILABLE
|
}
|
||||||
if (old_first == NULL) {
|
|
||||||
LWIP_HOOK_MEMP_AVAILABLE(type);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|||||||
2343
ext/lwip/src/core/netif.c
Normal file → Executable file
2343
ext/lwip/src/core/netif.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
2809
ext/lwip/src/core/pbuf.c
Normal file → Executable file
2809
ext/lwip/src/core/pbuf.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1025
ext/lwip/src/core/raw.c
Normal file → Executable file
1025
ext/lwip/src/core/raw.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
338
ext/lwip/src/core/stats.c
Normal file → Executable file
338
ext/lwip/src/core/stats.c
Normal file → Executable file
@@ -1,169 +1,169 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Statistics module
|
* Statistics module
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/debug.h"
|
#include "lwip/debug.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct stats_ lwip_stats;
|
struct stats_ lwip_stats;
|
||||||
|
|
||||||
void
|
void
|
||||||
stats_init(void)
|
stats_init(void)
|
||||||
{
|
{
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
#if MEM_STATS
|
#if MEM_STATS
|
||||||
lwip_stats.mem.name = "MEM";
|
lwip_stats.mem.name = "MEM";
|
||||||
#endif /* MEM_STATS */
|
#endif /* MEM_STATS */
|
||||||
#endif /* LWIP_DEBUG */
|
#endif /* LWIP_DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_STATS_DISPLAY
|
#if LWIP_STATS_DISPLAY
|
||||||
void
|
void
|
||||||
stats_display_proto(struct stats_proto *proto, const char *name)
|
stats_display_proto(struct stats_proto *proto, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
||||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
|
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
|
||||||
LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
|
LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
|
||||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
|
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
|
||||||
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr));
|
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr));
|
||||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr));
|
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr));
|
||||||
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr));
|
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr));
|
||||||
LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr));
|
LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr));
|
||||||
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr));
|
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr));
|
||||||
LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr));
|
LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr));
|
||||||
LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err));
|
LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err));
|
||||||
LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
|
LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IGMP_STATS || MLD6_STATS
|
#if IGMP_STATS || MLD6_STATS
|
||||||
void
|
void
|
||||||
stats_display_igmp(struct stats_igmp *igmp, const char *name)
|
stats_display_igmp(struct stats_igmp *igmp, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
||||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
||||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
||||||
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
|
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
|
||||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
|
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
|
||||||
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
|
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
|
||||||
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
|
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
|
||||||
LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
|
LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
|
||||||
LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group));
|
LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group));
|
||||||
LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general));
|
LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general));
|
||||||
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
|
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
|
||||||
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
|
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
|
||||||
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
|
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
|
||||||
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
|
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report));
|
||||||
}
|
}
|
||||||
#endif /* IGMP_STATS || MLD6_STATS */
|
#endif /* IGMP_STATS || MLD6_STATS */
|
||||||
|
|
||||||
#if MEM_STATS || MEMP_STATS
|
#if MEM_STATS || MEMP_STATS
|
||||||
void
|
void
|
||||||
stats_display_mem(struct stats_mem *mem, const char *name)
|
stats_display_mem(struct stats_mem *mem, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
||||||
LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used));
|
LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used));
|
||||||
LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max));
|
LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max));
|
||||||
LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
|
LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MEMP_STATS
|
#if MEMP_STATS
|
||||||
void
|
void
|
||||||
stats_display_memp(struct stats_mem *mem, int index)
|
stats_display_memp(struct stats_mem *mem, int index)
|
||||||
{
|
{
|
||||||
if (index < MEMP_MAX) {
|
if (index < MEMP_MAX) {
|
||||||
stats_display_mem(mem, mem->name);
|
stats_display_mem(mem, mem->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* MEMP_STATS */
|
#endif /* MEMP_STATS */
|
||||||
#endif /* MEM_STATS || MEMP_STATS */
|
#endif /* MEM_STATS || MEMP_STATS */
|
||||||
|
|
||||||
#if SYS_STATS
|
#if SYS_STATS
|
||||||
void
|
void
|
||||||
stats_display_sys(struct stats_sys *sys)
|
stats_display_sys(struct stats_sys *sys)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
|
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
|
||||||
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
||||||
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
||||||
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
||||||
LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used));
|
LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used));
|
||||||
LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max));
|
LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max));
|
||||||
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
|
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
|
||||||
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
||||||
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
||||||
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
|
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err));
|
||||||
}
|
}
|
||||||
#endif /* SYS_STATS */
|
#endif /* SYS_STATS */
|
||||||
|
|
||||||
void
|
void
|
||||||
stats_display(void)
|
stats_display(void)
|
||||||
{
|
{
|
||||||
s16_t i;
|
s16_t i;
|
||||||
|
|
||||||
LINK_STATS_DISPLAY();
|
LINK_STATS_DISPLAY();
|
||||||
ETHARP_STATS_DISPLAY();
|
ETHARP_STATS_DISPLAY();
|
||||||
IPFRAG_STATS_DISPLAY();
|
IPFRAG_STATS_DISPLAY();
|
||||||
IP6_FRAG_STATS_DISPLAY();
|
IP6_FRAG_STATS_DISPLAY();
|
||||||
IP_STATS_DISPLAY();
|
IP_STATS_DISPLAY();
|
||||||
ND6_STATS_DISPLAY();
|
ND6_STATS_DISPLAY();
|
||||||
IP6_STATS_DISPLAY();
|
IP6_STATS_DISPLAY();
|
||||||
IGMP_STATS_DISPLAY();
|
IGMP_STATS_DISPLAY();
|
||||||
MLD6_STATS_DISPLAY();
|
MLD6_STATS_DISPLAY();
|
||||||
ICMP_STATS_DISPLAY();
|
ICMP_STATS_DISPLAY();
|
||||||
ICMP6_STATS_DISPLAY();
|
ICMP6_STATS_DISPLAY();
|
||||||
UDP_STATS_DISPLAY();
|
UDP_STATS_DISPLAY();
|
||||||
TCP_STATS_DISPLAY();
|
TCP_STATS_DISPLAY();
|
||||||
MEM_STATS_DISPLAY();
|
MEM_STATS_DISPLAY();
|
||||||
for (i = 0; i < MEMP_MAX; i++) {
|
for (i = 0; i < MEMP_MAX; i++) {
|
||||||
MEMP_STATS_DISPLAY(i);
|
MEMP_STATS_DISPLAY(i);
|
||||||
}
|
}
|
||||||
SYS_STATS_DISPLAY();
|
SYS_STATS_DISPLAY();
|
||||||
}
|
}
|
||||||
#endif /* LWIP_STATS_DISPLAY */
|
#endif /* LWIP_STATS_DISPLAY */
|
||||||
|
|
||||||
#endif /* LWIP_STATS */
|
#endif /* LWIP_STATS */
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user