Răsfoiți Sursa

[lwIP] remove lwip-2.0.0

bernard 8 ani în urmă
părinte
comite
e7f888e24b
100 a modificat fișierele cu 2 adăugiri și 48204 ștergeri
  1. 0 3
      components/net/KConfig
  2. 2 2
      components/net/SConscript
  3. 0 4130
      components/net/lwip-2.0.0/CHANGELOG
  4. 0 33
      components/net/lwip-2.0.0/COPYING
  5. 0 5
      components/net/lwip-2.0.0/FILES
  6. 0 100
      components/net/lwip-2.0.0/README
  7. 0 81
      components/net/lwip-2.0.0/SConscript
  8. 0 228
      components/net/lwip-2.0.0/UPGRADING
  9. 0 9
      components/net/lwip-2.0.0/doc/FILES
  10. 0 117
      components/net/lwip-2.0.0/doc/NO_SYS_SampleCode.c
  11. 0 58
      components/net/lwip-2.0.0/doc/contrib.txt
  12. 0 1
      components/net/lwip-2.0.0/doc/doxygen/generate.bat
  13. 0 1
      components/net/lwip-2.0.0/doc/doxygen/generate.sh
  14. 0 2505
      components/net/lwip-2.0.0/doc/doxygen/lwip.Doxyfile
  15. 0 126
      components/net/lwip-2.0.0/doc/doxygen/main_page.h
  16. 0 10
      components/net/lwip-2.0.0/doc/doxygen/output/index.html
  17. BIN
      components/net/lwip-2.0.0/doc/doxygen_docs.zip
  18. 0 113
      components/net/lwip-2.0.0/doc/mdns.txt
  19. 0 529
      components/net/lwip-2.0.0/doc/ppp.txt
  20. 0 499
      components/net/lwip-2.0.0/doc/rawapi.txt
  21. 0 120
      components/net/lwip-2.0.0/doc/savannah.txt
  22. 0 303
      components/net/lwip-2.0.0/doc/sys_arch.txt
  23. 0 15
      components/net/lwip-2.0.0/src/FILES
  24. 0 177
      components/net/lwip-2.0.0/src/Filelists.mk
  25. 0 995
      components/net/lwip-2.0.0/src/api/api_lib.c
  26. 0 1943
      components/net/lwip-2.0.0/src/api/api_msg.c
  27. 0 117
      components/net/lwip-2.0.0/src/api/err.c
  28. 0 246
      components/net/lwip-2.0.0/src/api/netbuf.c
  29. 0 413
      components/net/lwip-2.0.0/src/api/netdb.c
  30. 0 221
      components/net/lwip-2.0.0/src/api/netifapi.c
  31. 0 2790
      components/net/lwip-2.0.0/src/api/sockets.c
  32. 0 518
      components/net/lwip-2.0.0/src/api/tcpip.c
  33. 0 179
      components/net/lwip-2.0.0/src/apps/httpd/fs.c
  34. 0 21
      components/net/lwip-2.0.0/src/apps/httpd/fs/404.html
  35. BIN
      components/net/lwip-2.0.0/src/apps/httpd/fs/img/sics.gif
  36. 0 47
      components/net/lwip-2.0.0/src/apps/httpd/fs/index.html
  37. 0 298
      components/net/lwip-2.0.0/src/apps/httpd/fsdata.c
  38. 0 50
      components/net/lwip-2.0.0/src/apps/httpd/fsdata.h
  39. 0 2619
      components/net/lwip-2.0.0/src/apps/httpd/httpd.c
  40. 0 114
      components/net/lwip-2.0.0/src/apps/httpd/httpd_structs.h
  41. 0 97
      components/net/lwip-2.0.0/src/apps/httpd/makefsdata/makefsdata
  42. 0 1033
      components/net/lwip-2.0.0/src/apps/httpd/makefsdata/makefsdata.c
  43. 0 13
      components/net/lwip-2.0.0/src/apps/httpd/makefsdata/readme.txt
  44. 0 663
      components/net/lwip-2.0.0/src/apps/lwiperf/lwiperf.c
  45. 0 2031
      components/net/lwip-2.0.0/src/apps/mdns/mdns.c
  46. 0 367
      components/net/lwip-2.0.0/src/apps/netbiosns/netbiosns.c
  47. 0 749
      components/net/lwip-2.0.0/src/apps/snmp/snmp_asn1.c
  48. 0 108
      components/net/lwip-2.0.0/src/apps/snmp/snmp_asn1.h
  49. 0 1349
      components/net/lwip-2.0.0/src/apps/snmp/snmp_core.c
  50. 0 76
      components/net/lwip-2.0.0/src/apps/snmp/snmp_core_priv.h
  51. 0 116
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2.c
  52. 0 182
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_icmp.c
  53. 0 375
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_interfaces.c
  54. 0 743
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_ip.c
  55. 0 227
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_snmp.c
  56. 0 377
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_system.c
  57. 0 594
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_tcp.c
  58. 0 357
      components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_udp.c
  59. 0 1668
      components/net/lwip-2.0.0/src/apps/snmp/snmp_msg.c
  60. 0 194
      components/net/lwip-2.0.0/src/apps/snmp/snmp_msg.h
  61. 0 120
      components/net/lwip-2.0.0/src/apps/snmp/snmp_netconn.c
  62. 0 156
      components/net/lwip-2.0.0/src/apps/snmp/snmp_pbuf_stream.c
  63. 0 73
      components/net/lwip-2.0.0/src/apps/snmp/snmp_pbuf_stream.h
  64. 0 100
      components/net/lwip-2.0.0/src/apps/snmp/snmp_raw.c
  65. 0 220
      components/net/lwip-2.0.0/src/apps/snmp/snmp_scalar.c
  66. 0 343
      components/net/lwip-2.0.0/src/apps/snmp/snmp_table.c
  67. 0 218
      components/net/lwip-2.0.0/src/apps/snmp/snmp_threadsync.c
  68. 0 445
      components/net/lwip-2.0.0/src/apps/snmp/snmp_traps.c
  69. 0 136
      components/net/lwip-2.0.0/src/apps/snmp/snmpv3.c
  70. 0 145
      components/net/lwip-2.0.0/src/apps/snmp/snmpv3_dummy.c
  71. 0 331
      components/net/lwip-2.0.0/src/apps/snmp/snmpv3_mbedtls.c
  72. 0 66
      components/net/lwip-2.0.0/src/apps/snmp/snmpv3_priv.h
  73. 0 726
      components/net/lwip-2.0.0/src/apps/sntp/sntp.c
  74. 0 417
      components/net/lwip-2.0.0/src/apps/tftp/tftp_server.c
  75. 0 35
      components/net/lwip-2.0.0/src/arch/include/arch/bpstruct.h
  76. 0 105
      components/net/lwip-2.0.0/src/arch/include/arch/cc.h
  77. 0 35
      components/net/lwip-2.0.0/src/arch/include/arch/epstruct.h
  78. 0 52
      components/net/lwip-2.0.0/src/arch/include/arch/perf.h
  79. 0 62
      components/net/lwip-2.0.0/src/arch/include/arch/sys_arch.h
  80. 0 732
      components/net/lwip-2.0.0/src/arch/sys_arch.c
  81. 0 218
      components/net/lwip-2.0.0/src/core/def.c
  82. 0 1433
      components/net/lwip-2.0.0/src/core/dns.c
  83. 0 610
      components/net/lwip-2.0.0/src/core/inet_chksum.c
  84. 0 383
      components/net/lwip-2.0.0/src/core/init.c
  85. 0 124
      components/net/lwip-2.0.0/src/core/ip.c
  86. 0 529
      components/net/lwip-2.0.0/src/core/ipv4/autoip.c
  87. 0 1932
      components/net/lwip-2.0.0/src/core/ipv4/dhcp.c
  88. 0 1224
      components/net/lwip-2.0.0/src/core/ipv4/etharp.c
  89. 0 393
      components/net/lwip-2.0.0/src/core/ipv4/icmp.c
  90. 0 792
      components/net/lwip-2.0.0/src/core/ipv4/igmp.c
  91. 0 1072
      components/net/lwip-2.0.0/src/core/ipv4/ip4.c
  92. 0 331
      components/net/lwip-2.0.0/src/core/ipv4/ip4_addr.c
  93. 0 833
      components/net/lwip-2.0.0/src/core/ipv4/ip4_frag.c
  94. 0 50
      components/net/lwip-2.0.0/src/core/ipv6/dhcp6.c
  95. 0 126
      components/net/lwip-2.0.0/src/core/ipv6/ethip6.c
  96. 0 350
      components/net/lwip-2.0.0/src/core/ipv6/icmp6.c
  97. 0 53
      components/net/lwip-2.0.0/src/core/ipv6/inet6.c
  98. 0 1110
      components/net/lwip-2.0.0/src/core/ipv6/ip6.c
  99. 0 292
      components/net/lwip-2.0.0/src/core/ipv6/ip6_addr.c
  100. 0 777
      components/net/lwip-2.0.0/src/core/ipv6/ip6_frag.c

+ 0 - 3
components/net/KConfig

@@ -15,9 +15,6 @@ config RT_USING_LWIP
             config RT_USING_LWIP141
                 bool "lwIP v1.4.1"
 
-            config RT_USING_LWIP200
-                bool "lwIP v2.0.0"
-
             config RT_USING_LWIP202
                 bool "lwIP v2.0.2"
         endchoice

+ 2 - 2
components/net/SConscript

@@ -8,8 +8,8 @@ cwd = GetCurrentDir()
 list = os.listdir(cwd)
 
 # the default version of LWIP is 1.4.1
-if not GetDepend('RT_USING_LWIP132') and not GetDepend('RT_USING_LWIP140') and not GetDepend('RT_USING_LWIP200') and not GetDepend('RT_USING_LWIP202'):
-    AddDepend('RT_USING_LWIP141')
+if not GetDepend('RT_USING_LWIP132') and not GetDepend('RT_USING_LWIP140') and not GetDepend('RT_USING_LWIP202'):
+    AddDepend('RT_USING_LWIP202')
 
 for d in list:
     path = os.path.join(cwd, d)

+ 0 - 4130
components/net/lwip-2.0.0/CHANGELOG

@@ -1,4130 +0,0 @@
-HISTORY
-
-(git master)
-
-  * [Enter new changes just after this line - do not remove this line]
-
-  ++ New features:
-
-  2016-07-27: Simon Goldschmidt
-  * opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default
-    implementation of timeouts
-
-  2016-07-xx: Dirk Ziegelmeier
-  * Large overhaul of doxygen documentation
-
-  2016-04-05: Simon Goldschmidt
-  * timers.h/.c: prepare for overriding current timeout implementation: all
-    stack-internal caclic timers are avaliable in the lwip_cyclic_timers array
-
-  2016-03-23: Simon Goldschmidt
-  * tcp: call accept-callback with ERR_MEM when allocating a pcb fails on
-    passive open to inform the application about this error
-    ATTENTION: applications have to handle NULL pcb in accept callback!
-
-  2016-02-22: Ivan Delamer
-  * Initial 6LoWPAN support
-
-  2016-02-XX to 2016-03-XX: Dirk Ziegelmeier
-  * Cleanup TCPIP thread sync methods in a way that it is possibe to use them
-    in arbitrary code that needs things to be done in TCPIP thread. Used to
-    decouple netconn, netif, ppp and 6LoWPAN from LWIP core.
-
-  2016-02-XX: Dirk Ziegelmeier
-  * Implement dual-stack support in RAW, UDP and TCP. Add new IP address
-    type IPADDR_ANY_TYPE for this. Netconn/Socket API: Dual-stack is
-    automatically supported when an IPv6 netconn/socket is created.
-
-  2015-12-26: Martin Hentschel and Dirk Ziegelmeier
-  * Rewrite SNMP agent. SNMPv2c + MIB compiler.
-
-  2015-11-12: Dirk Ziegelmeier
-  * Decouple SNMP stack from lwIP core and move stack to apps/ directory.
-    Breaking change: Users have to call snmp_init() now!
-
-  2015-11-12: Dirk Ziegelmeier
-  * Implement possibility to declare private memory pools. This is useful to
-    decouple some apps from the core (SNMP stack) or make contrib app usage
-    simpler (httpserver_raw)
-
-  2015-10-09: Simon Goldschmidt
-  * started to move "private" header files containing implementation details to
-    "lwip/priv/" include directory to seperate the API from the implementation.
-
-  2015-10-07: Simon Goldschmidt
-  * added sntp client as first "supported" application layer protocol implementation
-    added 'apps' folder
-
-  2015-09-30: Dirk Ziegelmeier
-  * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance
-    implementation by aggregating the "base class" (struct mib_node) in all
-    derived node classes to get more type-safe code
-
-  2015-09-23: Simon Goldschmidt
-  * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to
-    ip_addr_t (so they can be used without conversion/temporary storage)
-
-  2015-09-08: Dirk Ziegelmeier
-  * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans
-    up the code and should allow integration of a 3rd party agent/mib2. Simple
-    counters are kept in MIB2_STATS, tree/table change function prototypes moved to
-    snmp_mib2.h.
-
-  2015-09-03: Simon Goldschmidt
-  * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records
-
-  2015-09-01: Simon Goldschmidt
-  * task #12178: hardware checksum capabilities can be configured per netif
-   (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function)
-
-  2015-08-30: Simon Goldschmidt
-  * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in
-    contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required)
-
-  2015-08-30: Simon Goldschmidt
-  * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point
-    to a routing function
-
-  2015-08-05: Simon Goldschmidt
-  * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF
-    and IP_MULTICAST_LOOP to be used without IGMP
-
-  2015-04-24: Simon Goldschmidt
-  * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to
-    check for the source of address assignment (replacement for NETIF_FLAG_DHCP)
-
-  2015-04-10: Simon Goldschmidt
-  * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled,
-    leaving an IPv6-only stack
-
-  2015-04-09: Simon Goldschmidt
-  * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed
-    ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP
-    version; ip_addr_t is used for all generic IP addresses for the API,
-    ip(4/6)_addr_t are only used internally or when initializing netifs or when
-    calling version-related functions
-
-  2015-03-24: Simon Goldschmidt
-  * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic
-    any more but passed through any netif (ENABLE_LOOPBACK has to be enabled)
-
-  2015-03-23: Simon Goldschmidt
-  * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP
-    addresses on multiple netifs should now be working correctly (if correctly
-    addressed by routing, that is)
-
-  2015-03-23: Simon Goldschmidt
-  * etharp.c: Stable etharp entries that are about to expire are now refreshed
-    using unicast to prevent unnecessary broadcast. Only if no answer is received
-    after 15 seconds, broadcast is used.
-
-  2015-03-06: Philip Gladstone
-  * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to
-    an interface)
-
-  2015-03-05: Simon Goldschmidt
-  * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling
-    is unclear): correclty separated administrative status of a netif (up/down)
-    from 'valid address' status
-    ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip
-    is used!
-
-  2015-02-26: patch by TabascoEye
-  * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address)
-
-  2015-02-22: chrysn, Simon Goldschmidt
-  * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take
-    const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed
-    port callbacks: netif_output_fn, netif_igmp_mac_filter_fn)
-
-  2015-02-19: Ivan Delamer
-  * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate
-    if DHCP is active is through netif->dhcp field.
-
-  2015-02-19: Ivan Delamer
-  * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections
-
-  2015-02-18: Simon Goldschmidt
-  * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly
-    connections half-closed by peer"
-
-  2015-02-18: Simon Goldschmidt
-  * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections
-    (see bug #39565)
-
-  2015-02-16: Claudius Zingerli, Sergio Caprile
-  * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP"
-
-  2015-02-14: Simon Goldschmidt
-  * opt.h, snmp*: added support for write-access community and dedicated
-    community for sending traps
-
-  2015-02-13: Simon Goldschmidt
-  * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when
-    a memp pool was empty and an item is now available
-
-  2015-02-13: Simon Goldschmidt
-  * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to
-    allocate additional header space for TX on netifs requiring additional headers
-
-  2015-02-12: chrysn
-  * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before
-    the next timeout is due, for NO_SYS==1)
-
-  2015-02-11: Nick van Ijzendoorn
-  * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number
-    with defined offset"
-
-  2015-02-11: Frederick Baksik
-  * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item
-
-  2015-02-11: Simon Goldschmidt
-  * api_msg.c, opt.h: started to implement fullduplex sockets/netconns
-    (note that this is highly unstable yet!)
-
-  2015-01-17: Simon Goldschmidt
-  * api: allow enabling socket API without (public) netconn API - netconn API is
-    still used by sockets, but keeping it private (static) should allow better
-    compiler optimizations
-
-  2015-01-16: Simon Goldschmidt
-  * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again
-    by implementing the calculation formula from RFC3390
-
-  2014-12-10: Simon Goldschmidt
-  * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread
-    instead of using one per netconn and per select call
-
-  2014-12-08: Simon Goldschmidt
-  * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform
-    (macro IP6H_VTCFL_SET())
-
-  2014-12-08: Simon Goldschmidt
-  * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX
-    (IPv6 and IPv4/v6 reassembly might not work yet)
-
-  2014-11-06: Simon Goldschmidt
-  * sockets.c/.h, init.c: lwip_socket_init() is not needed any more
-    -> compatibility define
-
-  2014-09-16: Simon Goldschmidt
-  * dns.c, opt.h: reduced ram usage by parsing DNS responses in place
-
-  2014-09-16: Simon Goldschmidt
-  * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at()
-
-  2014-09-15: Simon Goldschmidt
-  * dns.c: added source port randomization to make the DNS client more robust
-    (see bug #43144)
-
-  2013-09-02: Simon Goldschmidt
-  * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and
-    PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that
-    do not need packing
-
-  2013-08-19: Simon Goldschmidt
-  * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special
-    networks
-
-  2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi)
-  * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with
-    multiple gateways
-
-  2013-04-20: Fatih Asici
-  * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets
-    with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them
-    via hook function LWIP_HOOK_VLAN_CHECK
-
-  2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko)
-  * patch #7885: modification of api modules to support FreeRTOS-MPU
-    (don't pass stack-pointers to other threads)
-
-  2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab")
-  * patch #6537/#7858: TCP window scaling support
-
-  2014-01-17: Jiri Engelthaler
-  * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and
-    IPv6 ICMP's
-
-  2012-08-22: Sylvain Rochet
-  * New PPP stack for lwIP, developed in ppp-new branch.
-    Based from pppd 2.4.5, released 2009-11-17, with huge changes to match
-    code size and memory requirements for embedded devices, including:
-    - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which
-      is more or less what pppd sys-* files are, so that we get something working
-      using the unix port.
-    - Merged some patchs from lwIP Git repository which add interesting features
-      or fix bugs.
-    - Merged some patchs from Debian pppd package which add interesting features
-      or fix bugs.
-    - Ported PPP timeout handling to the lwIP timers system
-    - Disabled all the PPP code using filesystem access, replaced in necessary cases
-      to configuration variables.
-    - Disabled all the PPP code forking processes.
-    - Removed IPX support, lwIP does not support IPX.
-    - Ported and improved random module from the previous PPP port.
-    - Removed samba TDB (file-driven database) usage, because it needs a filesystem.
-    - MS-CHAP required a DES implementation, we added the latest PolarSSL DES
-      implementation which is under a BSD-ish license.
-    - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be
-      used in embedded devices with reduced memory footprint.
-    - Removed PPP configuration file parsing support. 
-    - Added macro definition EAP_SUPPORT to make EAP support optional.
-    - Added macro definition CHAP_SUPPORT to make CHAP support optional.
-    - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional.
-    - Added macro definition PAP_SUPPORT to make PAP support optional.
-    - Cleared all Linux syscall calls.
-    - Disabled demand support using a macro, so that it can be ported later.
-    - Disabled ECP support using a macro, so that it can be ported later.
-    - Disabled CCP support using a macro, so that it can be ported later.
-    - Disabled CBCP support using a macro, so that it can be ported later.
-    - Disabled LQR support using a macro, so that it can be ported later.
-    - Print packet debug feature optional, through PRINTPKT_SUPPORT
-    - Removed POSIX signal usage.
-    - Fully ported PPPoS code from the previous port.
-    - Fully ported PPPoE code from the previous port.
-    - Fully ported VJ compression protocol code from the previous port.
-    - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF.
-    - Disabled PPP server support using a macro, so that it can be ported later.
-    - Switched all PPP debug to lwIP debug system.
-    - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere,
-      removed all global variables everywhere, did everything necessary for
-      the PPP stack to support more than one PPP session (pppd only support
-      one session per process).
-    - Removed the statically allocated output buffer, now using PBUF.
-    - Improved structure size of all PPP modules, deep analyze of code to reduce
-      variables size to the bare minimum. Switched all boolean type (char type in
-      most architecture) to compiler generated bitfields.
-    - Added PPP IPv6 support, glued lwIP IPv6 support to PPP.
-    - Now using a persistent netif interface which can then be used in lwIP
-      functions requiring a netif.
-    - Now initializing PPP in lwip_init() function.
-    - Reworked completely the PPP state machine, so that we don't end up in
-      anymore in inconsistent state, especially with PPPoE.
-    - Improved the way we handle PPP reconnection after disconnect, cleaning
-      everything required so that we start the PPP connection again from a
-      clean state.
-    - Added PPP holdoff support, allow the lwIP user to wait a little bit before
-      reconnecting, prevents connection flood, especially when using PPPoL2TP.
-    - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client
-      feature to lwIP, L2TP being a widely used tunnel protocol.
-    - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...)
-    - Added PPP API "sequential" thread-safe API, based from NETIFAPI.
-
-  2011-07-21: Simon Goldschmidt
-  * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes
-    ioctl/FIONREAD return the size of the next pending datagram.
-
-  2011-05-25: Simon Goldschmidt
-  * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c,
-    combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4
-    and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP
-    code so that the code is more readable.
-
-  2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt)
-  * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to
-    Ivan! (this is work in progress: we're just post release anyway :-)
-
-
-  ++ Bugfixes:
-
-  2016-08-23: Simon Goldschmidt
-  * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need
-    it any more after implementing unicast ARP renewal towards arp entry timeout
-
-  2016-07-20: Simon Goldschmidt
-  * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC)
-
-  2016-07-21: Simon Goldschmidt (patch by Ambroz Bizjak)
-  * tcp_in.c, tcp_out.c: fixed bug #48543 (TCP sent callback may prematurely
-    report sent data when only part of a segment is acked) and don't include
-    SYN/FIN in snd_buf counter
-
-  2016-07-19: Simon Goldschmidt
-  * etharp.c: fixed bug #48477 (ARP input packet might update static entry)
-
-  2016-07-11: Simon Goldschmidt
-  * tcp_in.c: fixed bug #48476 (TCP sent callback called wrongly due to picking
-    up old pcb->acked
-
-  2016-06-30: Simon Goldschmidt (original patch by Fabian Koch)
-  * tcp_in.c: fixed bug #48170 (Vulnerable to TCP RST spoofing)
-
-  2016-05-20: Dirk Ziegelmeier
-  * sntp.h/.c: Fix return value of sntp_getserver() call to return a pointer
-
-  2016-04-05: Simon Goldschmidt (patch by Philip Gladstone)
-  * udp.c: patch #8358: allow more combinations of listening PCB for IPv6
-
-  2016-04-05: Simon Goldschmidt
-  * netconn/socket API: fixed bug# 43739 (Accept not reporting errors about
-    aborted connections): netconn_accept() returns ERR_ABRT (sockets: ECONNABORTED)
-    for aborted connections, ERR_CLSD (sockets: EINVAL) if the listening netconn
-    is closed, which better seems to follow the standard.
-
-  2016-03-23: Florent Matignon
-  * dhcp.c: fixed bug #38203: DHCP options are not recorded in all DHCP ack messages
-
-  2016-03-22: Simon Goldschmidt
-  * tcp: changed accept handling to be done internally: the application does not
-    have to call tcp_accepted() any more. Instead, when delaying accept (e.g. sockets
-    do), call tcp_backlog_delayed()/tcp_backlog_accepted() (fixes bug #46696)
-
-  2016-03-22: Simon Goldschmidt
-  * dns.c: ignore dns response parsing errors, only abort resolving for correct
-    responses or error responses from correct server (bug #47459)
-
-  2016-03-17: Simon Goldschmidt
-  * api_msg.c: fixed bug #47448 (netconn/socket leak if RST is received during close)
-
-  2016-03-17: Joel Cunningham
-  * api_msg.c: don't fail closing a socket/netconn when failing to allocate the
-    FIN segment; blocking the calling thread for a while is better than risking
-    leaking a netconn/socket (see bug #46701)
-
-  2016-03-16: Joel Cunningham
-  * tcp_out.c: reset rto timer on fast retransmission
-
-  2016-03-16: Deomid Ryabkov
-  * tcp_out.c: fixed bug #46384 Segment size calculation bug with MSS != TCP_MSS
-
-  2016-03-05: Simon Goldschmidt
-  * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error
-
-  2015-11-19: fix by Kerem Hadimli
-  * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new
-    netconn was already closed because of peer behavior
-
-  2015-11-12: fix by Valery Ushakov
-  * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort()
-
-  2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt
-  * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089,
-    reduce ram/rom usage of tables): incompatible change for private MIBs
-
-  2015-09-30: Simon Goldschmidt
-  * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range
-    of all address parts
-
-  2015-08-28: Simon Goldschmidt
-  * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh
-    is set to the full send window for active open, too, and is updated once
-    after SYN to ensure the correct send window is used
-
-  2015-08-28: Simon Goldschmidt
-  * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks
-
-  2015-08-26: Simon Goldschmidt
-  * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms:
-    define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header
-    instead of referencing it, which gives more room for struct ip6_reass_helper
-
-  2015-08-25: Simon Goldschmidt
-  * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK
-
-  2015-08-20: Manoj Kumar
-  * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255
-    from SNMP agent
-
-  2015-08-19: Jens Nielsen
-  * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple
-    interfaces handling
-
-  2015-08-19: Simon Goldschmidt (patch by "Sandra")
-  * dns.c: fixed bug #45004: dns response without answer might be discarded
-
-  2015-08-18: Chrysn
-  * timers.c: patch #8704 fix sys_timeouts_sleeptime function
-
-  2015-07-01: Erik Ekman
-  * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset
-    is at start of pbuf in chain)
-
-  2015-05-19: Simon Goldschmidt
-  * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after
-    fixing bug #38204)
-
-  2015-03-21: Simon Goldschmidt (patch by Homyak)
-  * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in
-    two places)
-
-  2015-03-21: Simon Goldschmidt
-  * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input()
-    after tcp_close())
-
-  2015-03-21: Simon Goldschmidt
-  * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for
-    data ACKed with the same ack as FIN)
-
-  2015-03-21: Simon Goldschmidt (patch by Christoffer Lind)
-  * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly)
-
-  2015-03-20: Simon Goldschmidt
-  * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message)
-
-  2015-03-19: Simon Goldschmidt
-  * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning
-    netconn->last_err (fixed bugs #38121 and #37676)
-
-  2015-03-09: Simon Goldschmidt
-  * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status)
-
-  2015-03-04: Simon Goldschmidt
-  * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation)
-
-  2015-03-04: Valery Ushakov
-  * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test)
-
-  2015-03-04: Zach Smith
-  * nd6.c: fixed bug #38153 (nd6_input() byte order issues)
-
-  2015-02-26: Simon Goldschmidt
-  * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif
-    remove)
-
-  2015-02-25: Simon Goldschmidt
-  * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted
-    packets), implemented task #12357 (Ensure that malicious packets don't
-    assert-fail): improved some pbuf_header calls to not assert-fail.
-
-  2015-02-25: patch by Joel Cunningham
-  * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast
-    datagrams)
-
-  2015-02-25: patch by Greg Renda
-  * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram)
-
-  2015-02-25: Simon Goldschmidt
-  * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership
-    are dropped when socket (not netconn!) is closed.
-
-  2015-02-25: Simon Goldschmidt
-  * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by
-    adding an optional default netif for multicast routing
-
-  2015-02-25: Simon Goldschmidt
-  * netconn API: fixed that netconn_connect still used message passing for
-    LWIP_TCPIP_CORE_LOCKING==1
-
-  2015-02-22: patch by Jens Nielsen
-  * icmp.c: fixed bug #38803 (Source address in broadcast ping reply)
-
-  2015-02-22: Simon Goldschmidt
-  * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip
-    (previously used by get/setsockopt only)
-
-  2015-02-18: Simon Goldschmidt
-  * sockets.c: Fixed select not reporting received FIN as 'readable' in certain
-    rare cases (bug #43779: select(), close(), and TCP retransmission error)
-
-  2015-02-17: Simon Goldschmidt
-  * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno":
-    return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already
-    connected
-
-  2015-02-17: Simon Goldschmidt
-  * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from
-    ipX_output are not processed". Now tcp_output(_segment) checks for the return
-    value of ipX_output and does not try to send more on error. A netif driver
-    can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers
-    are available again.
-
-  2015-02-14: patches by Freddie Chopin
-  * snmp*: made community writable, fixed some const pointers
-
-  2015-02-13: Simon Goldschmidt
-  * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP"
-
-  2015-02-12: Simon Goldschmidt
-  * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass
-    inp to higher layers": now the accepting netif is passed up, but the input
-    netif is available through ip_current_input_netif() if required.
-
-  2015-02-11: patch by hichard
-  * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6"
-
-  2015-02-10: Simon Goldschmidt
-  * netconn API: fixed that netconn_close/netconn_delete still used message passing
-    for LWIP_TCPIP_CORE_LOCKING==1
-
-  2015-02-10: Simon Goldschmidt
-  * netconn/socket api: fixed bug #44225 "closing TCP socket should time out
-    eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets
-    times out after 20 seconds or after the configured SND_TIMEOUT or depending
-    on the linger settings.
-
-  2015-01-27: Simon Goldschmidt
-  * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR,
-    fixed return value of lwip_netconn_do_close on unconnected netconns
-
-  2015-01-17: Simon Goldschmidt
-  * sockets.c: fixed bug #43361 select() crashes with stale FDs
-
-  2015-01-17: Simon Goldschmidt
-  * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes"
-    by rewriting set/getsockopt functions to combine checks with the actual code
-    and add more NULL checks; this also fixes that CORE_LOCKING used message
-    passing for set/getsockopt.
-
-  2014-12-19: Simon Goldschmidt
-  * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only
-    when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for
-    compatibility reasons)
-
-  2014-12-17: Simon Goldschmidt
-  * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for
-    no-copy data with odd length
-
-  2014-12-10: Simon Goldschmidt
-  * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO
-    take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can
-    be used to revert to the old 'winsock' style behaviour)
-    Fixed implementation of SO_ACCEPTCONN to just look at the pcb state
-
-  2014-12-09: Simon Goldschmidt
-  * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded
-
-  2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing)
-  * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278
-    event_callback() handle context switch when calling sys_sem_signal()
-
-  2014-10-21: Simon Goldschmidt
-  * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set
-
-  2014-09-16: Kevin Cernekee
-  * dns.c: patch #8480 Fix handling of dns_seqno wraparound
-
-  2014-09-16: Simon Goldschmidt
-  * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN
-    when sending FIN
-
-  2014-09-03: Simon Goldschmidt
-  * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error
-
-  2014-09-02: Simon Goldschmidt
-  * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before
-    listen() will cause a error
-
-  2014-09-02: Simon Goldschmidt
-  * sockets.c: fixed bug #42117 lwip_fcntl does not set errno
-
-  2014-09-02: Simon Goldschmidt
-  * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list
-
-  2014-08-20: Simon Goldschmidt
-  * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to
-    non-randomized TXIDs
-
-  2014-06-03: Simon Goldschmidt
-  * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in
-    tcp_input function
-
-  2014-05-20: Simon Goldschmidt
-  * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state
-
-  2014-05-19: Simon Goldschmidt
-  * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores
-    from header include guards)
-
-  2014-04-08: Simon Goldschmidt
-  * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window)
-
-  2014-04-06: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received
-    unacceptable ACK
-
-  2014-04-06: Simon Goldschmidt
-  * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery
-    is invalid when an IP is set to thet netif.
-
-  2014-03-14: Simon Goldschmidt
-  * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1
-
-  2014-03-11: Simon Goldschmidt (patch by Mason)
-  * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for
-    POSIX-compliance
-
-  2014-02-27: Simon Goldschmidt
-  * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST
-
-  2014-02-27: Simon Goldschmidt
-  * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when
-    IP_SOF_BROADCAST_RECV==1
-
-  2014-02-27: Simon Goldschmidt
-  * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on
-    unconnected/listening TCP sockets
-
-  2014-02-27: Simon Goldschmidt
-  * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1
-
-  2014-02-25: Simon Goldschmidt
-  * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface
-
-  2014-02-25: Simon Goldschmidt, patch by Fatih Asici
-  * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind()
-
-  2014-02-25: Simon Goldschmidt
-  * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly;
-    renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match()
-
-  2014-02-25: Simon Goldschmidt
-  * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1
-
-  2014-02-22: Simon Goldschmidt (patch by Amir Shalem)
-  * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3)
-
-  2014-02-22: Simon Goldschmidt (patch by Amir Shalem)
-  * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry
-
-  2014-02-20: Simon Goldschmidt
-  * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with
-    MEM_ALIGNMENT = 8
-
-  2014-02-20: Simon Goldschmidt
-  * sockets.c: fixed bug #39882 No function shall set errno to 0
-
-  2014-02-20: Simon Goldschmidt
-  * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255
-
-  2014-02-20: Simon Goldschmidt
-  * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow
-
-  2014-01-08: Stathis Voukelatos
-  * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool
-    creation macro
-
-  2014-01-18: Brian Fahs
-  * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize
-    when necessary
-
-  2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt
-  * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback
-
-  2014-01-16: Stathis Voukelatos
-  * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0
-
-  2014-01-14: "Freddie Chopin"
-  * snmp.h, mib2.c: fixed constness and spelling of sysdescr
-
-  2014-01-14: Simon Goldschmidt (patch by Thomas Faber)
-  * tcpip.c: patch #8241: Fix implicit declaration of ip_input with
-    LWIP_TCPIP_CORE_LOCKING_INPUT disabled
-
-  2014-01-14: chrysn
-  * timers.c: patch #8244 make timeouts usable reliably from outside of the
-    timeout routine
-
-  2014-01-10: Simon Goldschmidt
-  * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly
-
-  2014-01-10: Simon Goldschmidt
-  * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1
-
-  2014-01-10: Simon Goldschmidt
-  * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop
-
-  2013-06-29: Simon Goldschmidt
-  * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs)
-
-  2013-06-29: Simon Goldschmidt
-  * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec
-
-  2013-04-24: patch by Liam <morepork>
-  * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert
-
-  2013-04-24: Simon Goldschmidt
-  * igmp.c: fixed possible division by zero
-
-  2013-04-24: Simon Goldschmidt
-  * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h
-
-  2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl):
-  * netif.c: fixed bug #38586 netif_loop_output() "deadlocks"
-
-  2013-01-15: Simon Goldschmidt
-  * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order
-
-  2013-01-15: Simon Goldschmidt
-  * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning
-
-  2013-01-14: Simon Goldschmidt
-  * dns.c: fixed bug #37705 Possible memory corruption in DNS query
-
-  2013-01-11: Simon Goldschmidt
-  * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it
-
-  2012-08-22: Simon Goldschmidt
-  * memp.c: fixed bug #37166: memp_sanity check loops itself
-
-  2012-08-13: Simon Goldschmidt
-  * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start
-    dereferences NULL
-
-  2012-08-13: Simon Goldschmidt
-  * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps
-    configured but no interfaces available
-
-  2012-08-13: Simon Goldschmidt
-  * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time
-
-  2012-05-11: Simon Goldschmidt (patch by Marty)
-  * memp.c: fixed bug #36412: memp.c does not compile when
-    MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1
-
-  2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet)
-  * ppp.c: fixed bug #36283 (PPP struct used on header size computation and
-    not packed)
-
-  2012-05-03: Simon Goldschmidt (patch by David Empson)
-  * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with
-    zero length)
-
-  2012-03-25: Simon Goldschmidt
-  * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed
-    for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1
-
-  2012-03-25: Simon Goldschmidt
-  * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space
-    pollution in api_msg.c and netifapi.c
-
-  2011-08-24: Simon Goldschmidt
-  * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard
-
-
-
-(STABLE-1.4.1)
-
-  ++ New features:
-
-  2012-03-25: Simon Goldschmidt (idea by Mason)
-  * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h
-    which are a simple wrapper to the correct lwIP include files.
- 
-  2012-01-16: Simon Goldschmidt
-  * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP
-
-  2011-12-17: Simon Goldschmidt
-  * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW)
-    (fixes bug #35061)
-
-  2011-09-27: Simon Goldschmidt
-  * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989)
-    (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h)
-
-  2011-09-21: Simon Goldschmidt
-  * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on
-    send (TCP only, bug #33820)
-
-  2011-09-21: Simon Goldschmidt
-  * init.c: Converted runtime-sanity-checks into compile-time checks that can
-    be disabled (since runtime checks can often not be seen on embedded targets)
-
-  2011-09-11: Simon Goldschmidt
-  * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file
-    to get a clear separation of which functions an application or port may use
-    (task #11281)
-
- 2011-09-11: Simon Goldschmidt
-  * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize
-    initial local TCP/UDP ports (so that different port ranges are used after
-    a reboot; bug #33818; this one added tcp_init/udp_init functions again)
-
-  2011-09-03: Simon Goldschmidt
-  * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302)
-
-  2011-08-24: Simon Goldschmidt
-  * opt.h, netif.h/.c: added netif remove callback (bug #32397)
-
-  2011-07-26: Simon Goldschmidt
-  * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter
-    function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN)
-
-  2011-07-21: Simon Goldschmidt (patch by hanhui)
-  * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour:
-    Added pbuf flags to mark incoming packets as link-layer broadcast/multicast.
-    Also added code to allow ip_forward() to forward non-broadcast packets to
-    the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1).
-
-  2011-06-26: Simon Goldschmidt (patch by Cameron Gutman)
-  * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that
-    pcb->state != LISTEN
-
-   2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage)
-  * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static
-    memory message
-
-
-  ++ Bugfixes:
-
-  2012-09-26: Simon Goldschmidt
-  * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object
-
-  2012-09-26: patch by Henrik Persson
-  * dhcp.c: patch #7843 Fix corner case with dhcp timeouts
-
-  2012-09-26: patch by Henrik Persson
-  * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet
-
-  2012-08-22: Simon Goldschmidt
-  * memp.c: fixed bug #37166: memp_sanity check loops itself
-
-  2012-05-08: Simon Goldschmidt
-  * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was
-    a debug-check issue only)
-
-  2012-03-27: Simon Goldschmidt
-  * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c
-
-  2012-03-27: Simon Goldschmidt (patch by Mason)
-  * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the
-    send MSS
-
-  2012-03-22: Simon Goldschmidt
-  * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward
- 
-  2012-03-20: Simon Goldschmidt (patch by Mason)
-  * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list
- 
-  2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic)
-  * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian,
-    possible bug on little endian system
-
-  2012-02-23: Simon Goldschmidt
-  * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway
-    (introduced when fixing bug# 33551)
-
-  2012-02-16: Simon Goldschmidt
-  * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP()
-    (bug #35541: PPP Memory Leak)
-
-  2012-02-16: Simon Goldschmidt
-  * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway
-    (introduced when fixing bug# 33551)
-
-  2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage)
-  * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed
-
-  2012-02-15: Simon Goldschmidt
-  * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with
-    MEMP_MEM_MALLOC==1
-
-  2012-02-12: Simon Goldschmidt
-  * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on
-    MSS > pcb->snd_wnd (by not creating segments bigger than half the window)
-
-  2012-02-11: Simon Goldschmidt
-  * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait
-    queue while closing
-
-  2012-01-22: Simon Goldschmidt
-  * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR)
-
-  2012-01-21: Simon Goldschmidt
-  * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb
-
-  2012-01-20: Simon Goldschmidt
-  * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths
-
- 2012-01-20: Simon Goldschmidt
-  * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy
-
-  2011-11-25: Simon Goldschmidt
-  * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt
-    tcp_active_pcbs in some cases
-
-  2011-11-23: Simon Goldschmidt
-  * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with
-    '#ifndef sys_msleep'
-
-  2011-11-22: Simon Goldschmidt
-  * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when
-    netif is brought down
-
-  2011-10-28: Simon Goldschmidt
-  * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks
-
-  2011-10-23: Simon Goldschmidt
-  * mem.c: fixed bug #34429: possible memory corruption with
-    LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1
-
-  2011-10-18: Simon Goldschmidt
-  * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard
-    error value
-
-  2011-10-18: Simon Goldschmidt
-  * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small
-    windows (bug #34176 select after non-blocking send times out)
-
-  2011-10-18: Simon Goldschmidt
-  * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't
-    consider netif->mtu, causes slow network
-
-  2011-10-18: Simon Goldschmidt
-  * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code
-
-  2011-10-18: Simon Goldschmidt
-  * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS
-
-  2011-10-17: Simon Goldschmidt
-  * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api
-
-  2011-10-13: Simon Goldschmidt
-  * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no
-    zero window is received) by starting the persist timer when a zero window is
-    received, not when we have more data queued for sending than fits into the
-    window
-
-  2011-10-13: Simon Goldschmidt
-  * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex
-
-  2011-10-13: Simon Goldschmidt
-  * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is
-    used and not all protocols are enabled
-
-  2011-10-12: Simon Goldschmidt
-  * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4
-
-  2011-10-09: Simon Goldschmidt
-  * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect
-    byte value when pcb->unacked != NULL
-
-  2011-10-09: Simon Goldschmidt
-  * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong
-
-  2011-09-27: Simon Goldschmidt
-  * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places...
-
-  2011-09-27: Simon Goldschmidt
-  * tcp_in.c: fixed bug #28288: Data after FIN in oos queue
-
-  2011-09-27: Simon Goldschmidt
-  * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf
-
-  2011-09-24: Simon Goldschmidt
-  * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1
-
-  2011-09-23: Simon Goldschmidt
-  * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for
-    the last packet including FIN can lose data
-
-  2011-09-22: Simon Goldschmidt
-  * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into
-    account
-
-  2011-09-21: Simon Goldschmidt
-  * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks
-    in init.c
-
-  2011-09-20: Simon Goldschmidt
-  * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts)
-
-  2011-09-11: Simon Goldschmidt
-  * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs
-    (bug #34019)
-
-  2011-09-09: Simon Goldschmidt
-  * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if
-    udp port matches
-
-  2011-09-03: Simon Goldschmidt
-  * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet
-    is aggregated and sent to application
-
-  2011-09-01: Simon Goldschmidt
-  * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared
-    to other options
-
-  2011-09-01: Simon Goldschmidt
-  * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno
-
-  2011-08-24: Simon Goldschmidt
-  * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling
-    accept() on UDP connections
-
-  2011-08-24: Simon Goldschmidt
-  * sockets.h: fixed bug #34057 socklen_t should be a typedef
-
-  2011-08-24: Simon Goldschmidt
-  * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo)
-
-  2011-08-24: Simon Goldschmidt
-  * dhcp.c: fixed bug #34122 dhcp: hostname can overflow
-
-  2011-08-24: Simon Goldschmidt
-  * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr
-
-  2011-08-22: Simon Goldschmidt
-  * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This
-    merely prevents nagle from not transmitting fast after closing.)
-
-  2011-07-22: Simon Goldschmidt
-  * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns
-    always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now
-    lwip_send() sends as much as possible for non-blocking sockets
-
-  2011-07-22: Simon Goldschmidt
-  * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented
-    for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
-    at regular intervals from main level.
-
-  2011-07-21: Simon Goldschmidt
-  * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by
-    sending an ARP request when an ARP entry is used in the last minute before
-    it would time out.
-
-  2011-07-04: Simon Goldschmidt
-  * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0.
-
-  2011-06-26: Simon Goldschmidt
-  * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by
-    updating its documentation only.
-
- 2011-06-26: Simon Goldschmidt
-  * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an
-    unaligned pointer.
-
-  2011-06-26: Simon Goldschmidt
-  * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1"
-
-   2011-05-25: Simon Goldschmidt
-  * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range)
-
-
-
-(STABLE-1.4.0)
-
-  ++ New features:
-
-  2011-03-27: Simon Goldschmidt
-  * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and
-    calculate it in tcp_zero_window_probe (the only place where it was used).
-
-  2010-11-21: Simon Goldschmidt
-  * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
-    (fixes bug #31525).
-
-  2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
-  * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
-    IP_MULTICAST_LOOP at socket- and raw-API level.
-
-  2010-06-16: Simon Goldschmidt
-  * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow
-    link-layer-addressed UDP traffic to be received while a netif is down (just
-    like DHCP during configuration)
-
-  2010-05-22: Simon Goldschmidt
-  * many many files: bug #27352: removed packing from ip_addr_t, the packed
-    version is now only used in protocol headers. Added global storage for
-    current src/dest IP address while in input functions.
-
-  2010-05-16: Simon Goldschmidt
-  * def.h: task #10391: Add preprocessor-macros for compile-time htonl
-    calculation (and use them throughout the stack where applicable)
-
-  2010-05-16: Simon Goldschmidt
-  * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool
-    instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h)
-
-  2010-05-16: Simon Goldschmidt
-  * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own
-    MEMP pool instead of the heap
-
-  2010-05-13: Simon Goldschmidt
-  * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added
-    new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast
-    packets to more than one pcb.
-
-  2010-05-02: Simon Goldschmidt
-  * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending
-    UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1
-
-  2010-04-30: Simon Goldschmidt
-  * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that
-    take a precalculated checksum, added pbuf_fill_chksum() to copy data
-    into a pbuf and at the same time calculating the checksum for that data
-
-  2010-04-29: Simon Goldschmidt
-  * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying
-    2-byte-aligned IP addresses and MAC addresses
-
-  2010-04-28: Patch by Bill Auerbach
-  * ip.c: Inline generating IP checksum to save a function call
-
-  2010-04-14: Simon Goldschmidt
-  * tcpip.h/.c, timers.c: Added an overridable define to get informed when the
-    tcpip_thread processes messages or timeouts to implement a watchdog.
-
-  2010-03-28: Simon Goldschmidt
-  * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing
-    fragment if LWIP_NETIF_TX_SINGLE_PBUF==1
-
-  2010-03-27: Simon Goldschmidt
-  * etharp.c: Speedup TX by moving code from find_entry to etharp_output/
-    etharp_query to prevent unnecessary function calls (inspired by
-    patch #7135).
-
-  2010-03-20: Simon Goldschmidt
-  * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code
-    since the linker cannot do this automatically to save space.
-
-  2010-03-20: Simon Goldschmidt
-  * opt.h, etharp.c/.h: Added support for static ARP table entries
-
-  2010-03-14: Simon Goldschmidt
-  * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum
-    when creating TCP segments, not when (re-)transmitting them.
-
-  2010-03-07: Simon Goldschmidt
-  * sockets.c: bug #28775 (select/event_callback: only check select_cb_list
-    on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code.
-    This should speed up receiving data on sockets as the select code in
-    event_callback is only executed when select is waiting.
-
-  2010-03-06: Simon Goldschmidt
-  * tcp_out.c: task #7013 (Create option to have all packets delivered to
-    netif->output in one piece): Always copy to try to create single pbufs
-    in tcp_write.
-
-  2010-03-06: Simon Goldschmidt
-  * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv
-    by not allocating a netbuf): added function netconn_recv_tcp_pbuf()
-    for tcp netconns to receive pbufs, not netbufs; use that function
-    for tcp sockets.
-
-  2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt
-  * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040:
-    Work on tcp_enqueue: Don't waste memory when chaining segments,
-    added option TCP_OVERSIZE to prevent creating many small pbufs when
-    calling tcp_write with many small blocks of data. Instead, pbufs are
-    allocated larger than needed and the space is used for later calls to
-    tcp_write.
-
-  2010-02-21: Simon Goldschmidt
-  * stats.c/.h: Added const char* name to mem- and memp-stats for easier
-    debugging.
-
-  2010-02-21: Simon Goldschmidt
-  * tcp.h (and usages), added tcp_impl.h: Splitted API and internal
-    implementation of tcp to make API usage cleare to application programmers
-
-  2010-02-14: Simon Goldschmidt/Stephane Lesage
-  * ip_addr.h: Improved some defines working on ip addresses, added faster
-    macro to copy addresses that cannot be NULL
-
-  2010-02-13: Simon Goldschmidt
-  * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non-
-    blocking send operation)
-
-  2010-02-12: Simon Goldschmidt
-  * sockets.c/.h: Added a minimal version of posix fctl() to have a
-    standardised way to set O_NONBLOCK for nonblocking sockets.
-
-  2010-02-12: Simon Goldschmidt
-  * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated
-    memory): added autoip_set_struct() and dhcp_set_struct() to let autoip
-    and dhcp work with user-allocated structs instead of callin mem_malloc
-
-  2010-02-12: Simon Goldschmidt/Jeff Barber
-  * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has
-    SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT
-
-  2010-02-12: Simon Goldschmidt
-  * sys layer: task #10139 (Prefer statically allocated memory): converted
-    mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t;
-    converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
-    task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX
-    to let sys.h use binary semaphores instead of mutexes - as before)
-
-  2010-02-09: Simon Goldschmidt (Simon Kallweit)
-  * timers.c/.h: Added function sys_restart_timeouts() from patch #7085
-    (Restart system timeout handling)
-
-  2010-02-09: Simon Goldschmidt
-  * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into
-    netif.c) - loopif does not have to be created by the port any more,
-    just define LWIP_HAVE_LOOPIF to 1.
-
-  2010-02-08: Simon Goldschmidt
-  * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa
-    inet_ntoa_r/ipaddr_ntoa_r
-
-  2010-02-08: Simon Goldschmidt
-  * netif.h: Added netif_s/get_igmp_mac_filter() macros
-
-  2010-02-05: Simon Goldschmidt
-  * netif.h: Added function-like macros to get/set the hostname on a netif
-
-  2010-02-04: Simon Goldschmidt
-  * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to
-    make changing the actual implementation behind the typedef easier.
-
-  2010-02-01: Simon Goldschmidt
-  * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool
-    for allocating memory when getaddrinfo() is called.
-
-  2010-01-31: Simon Goldschmidt
-  * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse
-    them once instead of parsing for every option. This also removes
-    the need for mem_malloc from dhcp_recv and makes it possible to
-    correctly retrieve the BOOTP file.
-
-  2010-01-30: simon Goldschmidt
-  * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect
-    the sockets array.
-
-  2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
-  * api.h, api_msg.c, sockets.c: Added except set support in select
-    (patch #6860)
-
-  2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
-  * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c:
-    Add non-blocking support for connect (partly from patch #6860),
-    plus many cleanups in socket & netconn API.
-
-  2010-01-27: Simon Goldschmidt
-  * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding
-    to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605
-
-  2010-01-26: Simon Goldschmidt
-  * snmp: Use memp pools for snmp instead of the heap; added 4 new pools.
-
-  2010-01-14: Simon Goldschmidt
-  * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback
-    by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback()
-
-  2010-01-13: Simon Goldschmidt
-  * mem.c: 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
-    (patch #6966 and bug #26133)
-
-  2010-01-10: Simon Goldschmidt (Bill Auerbach)
-  * opt.h, memp.c: patch #6822 (Add option to place memory pools in
-    separate arrays)
-
-  2010-01-10: Simon Goldschmidt
-  * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define
-    LWIP_RAND() for lwip-wide randomization (to be defined in cc.h)
-
-  2009-12-31: Simon Goldschmidt
-  * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h
-    added timers.c/.h: Separated timer implementation from semaphore/mbox
-    implementation, moved timer implementation to timers.c/.h, timers are
-    now only called from tcpip_thread or by explicitly checking them.
-    (TASK#7235)
-
-  2009-12-27: Simon Goldschmidt
-  * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option
-    LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE)
-
-
-  ++ Bugfixes:
-
-  2011-04-20: Simon Goldschmidt
-  * sys_arch.txt: sys_arch_timeouts() is not needed any more.
-
-  2011-04-13: Simon Goldschmidt
-  * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by
-    using ports in the IANA private/dynamic range (49152 through 65535).
-
-  2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl:
-  * etharp.h/.c: Fixed broken VLAN support.
-
-  2011-03-27: Simon Goldschmidt
-  * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp
-    pcbs) by checking if the pcb was bound (local_port != 0).
-
-  2011-03-27: Simon Goldschmidt
-  * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice)
-
-  2011-03-27: Simon Goldschmidt
-  * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and
-    raw pcbs with LWIP_TCPIP_CORE_LOCKING==1.
-  
-  2011-03-27: Simon Goldschmidt
-  * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route
-    is present never times out) by starting retransmission timer before checking
-    route.
-
-  2011-03-22: Simon Goldschmidt
-  * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only
-    calling sio_read_abort() if the file descriptor is valid.
-
-  2011-03-14: Simon Goldschmidt
-  * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect
-    more than once can render a socket useless) since it mainly involves changing
-    "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal.
-
-  2011-03-13: Simon Goldschmidt
-  * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing
-    err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN:
-    use EALRADY instead of -1
-
-  2011-03-13: Simon Goldschmidt
-  * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the
-    connection has been aborted by err_tcp (since this is not a normal closing
-    procedure).
-
-  2011-03-13: Simon Goldschmidt
-  * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind
-    with pcb->state != CLOSED
-
-  2011-02-17: Simon Goldschmidt
-  * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in
-    documentation
-
-  2011-02-17: Simon Goldschmidt
-  * many files: Added missing U/UL modifiers to fix 16-bit-arch portability.
-
-  2011-01-24: Simon Goldschmidt
-  * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
-
-  2010-12-02: Simon Goldschmidt
-  * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
-
-  2010-11-23: Simon Goldschmidt
-  * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
-    LWIP_SO_RCVBUF and ioctl/FIONREAD.
-
-  2010-11-23: Simon Goldschmidt
-  * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
-    least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
-
-  2010-11-23: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
-    refusing 'refused_data' again.
-  
-  2010-11-22: Simon Goldschmidt
-  * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
-    after a successful nonblocking connection.
-
-  2010-11-22: Simon Goldschmidt
-  * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
-    must be sent link-local
-
-  2010-11-22: Simon Goldschmidt
-  * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
-    LWIP_TIMERS==0
-
-  2010-11-20: Simon Goldschmidt
-  * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
-
-  2010-11-20: Simon Goldschmidt
-  * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
-    resemble other stacks.
-
-  2010-11-20: Simon Goldschmidt
-  * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
-    no-copy TCP writes will never succeed.
-
-  2010-11-20: Simon Goldschmidt
-  * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
-    not match documentation: return ERR_ARG instead of ERR_VAL if not
-    initialized or wrong argument.
-
-  2010-10-20: Simon Goldschmidt
-  * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
-
-  2010-10-05: Simon Goldschmidt
-  * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
-    replugging the network cable after an AutoIP address was assigned.
-
-  2010-08-10: Simon Goldschmidt
-  * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
-
-  2010-08-03: Simon Goldschmidt
-  * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
-
-  2010-08-01: Simon Goldschmidt (patch by Greg Renda)
-  * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
-    endian architectures)
-  
-  2010-07-28: Simon Goldschmidt
-  * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
-    disabled.
-  
-  2010-07-27: Simon Goldschmidt
-  * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
-    harm but never did anything
-  
-  2010-07-21: Simon Goldschmidt
-  * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
-    add IP options)
-
-  2010-07-16: Kieran Mansley
-  * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator 
-
-  2010-07-10: Simon Goldschmidt
-  * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options
-
-  2010-06-30: Simon Goldschmidt
-  * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in
-    netconn_delete)
-
-  2010-06-28: Kieran Mansley
-  * timers.c remove unportable printing of C function pointers
-
-  2010-06-24: Simon Goldschmidt
-  * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag
-    NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading
-
-  2010-06-24: Simon Goldschmidt
-  * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly
-    implemented shutdown at socket level.
-
-  2010-06-21: Simon Goldschmidt
-  * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has
-    problems with zero-copy DMA MACs) by adding custom pbufs and implementing
-    custom pbufs that reference other (original) pbufs. Additionally set
-    IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side.
-
-  2010-06-15: Simon Goldschmidt
-  * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses
-
-  2010-06-14: Simon Goldschmidt
-  * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses
-
-  2010-06-12: Simon Goldschmidt
-  * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop
-    state
-
-  2010-05-17: Simon Goldschmidt
-  * netdb.c: Correctly NULL-terminate h_addr_list
-
-  2010-05-16: Simon Goldschmidt
-  * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent
-    "symbol already defined" i.e. when linking to winsock
-
-  2010-05-05: Simon Goldschmidt
-  * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may
-    overflow)
-
-  2010-04-21: Simon Goldschmidt
-  * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening
-    connection)
-
-  2010-03-28: Luca Ceresoli
-  * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers
-
-  2010-03-27: Luca Ceresoli
-  * mib2.c: patch #7130: remove meaningless const qualifiers
-
-  2010-03-26: Simon Goldschmidt
-  * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too
-
-  2010-03-26: Simon Goldschmidt
-  * various files: Fixed compiling with different options disabled (TCP/UDP),
-    triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled
-
-  2010-03-25: Simon Goldschmidt
-  * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly
-
-  2010-03-25: Simon Goldschmidt
-  * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side
-    overrunning our rcv_wnd in ooseq case.
-
-  2010-03-22: Simon Goldschmidt
-  * tcp.c: tcp_listen() did not copy the pcb's prio.
-
-  2010-03-19: Simon Goldschmidt
-  * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set
-
-  2010-03-14: Simon Goldschmidt
-  * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports
-    where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h
-    and basing PBUF_LINK_HLEN on it.
-
-  2010-03-08: Simon Goldschmidt
-  * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections
-    when assiging routable address): when checking incoming packets and
-    aborting existing connection on address change, filter out link-local
-    addresses.
-
-  2010-03-06: Simon Goldschmidt
-  * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING
-
-  2010-03-06: Simon Goldschmidt
-  * ipv4/ip.c: Don't try to forward link-local addresses
-
-  2010-03-06: Simon Goldschmidt
-  * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal-
-    addresses to gw
-
-  2010-03-05: Simon Goldschmidt
-  * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type
-    and state.
-
-  2010-03-05: Simon Goldschmidt
-  * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split
-    into multiple calls to tcp_write.    
-
-  2010-02-21: Simon Goldschmidt
-  * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep
-    the implementation of DNS_USES_STATIC_BUF==1)
-
-  2010-02-20: Simon Goldschmidt
-  * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement
-    close() vs. shutdown(). Now the application does not get any more
-    recv callbacks after calling tcp_close(). Added tcp_shutdown().
-
-  2010-02-19: Simon Goldschmidt
-  * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent
-    confusion with realloc()
-
-  2010-02-15: Simon Goldschmidt/Stephane Lesage
-  * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK
-    (fixes bug #28899)
-
-  2010-02-14: Simon Goldschmidt
-  * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with
-    LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and
-    admin-status of a netif are up
-
-  2010-02-14: Simon Goldschmidt
-  * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet
-    reception and is not really necessary
-
-  2010-02-14: Simon Goldschmidt
-  * etharp.c/.h: Fixed ARP input processing: only add a new entry if a
-    request was directed as us (RFC 826, Packet Reception), otherwise
-    only update existing entries; internalized some functions
-
-  2010-02-14: Simon Goldschmidt
-  * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be
-    disabled on netif used for PPPoE) by adding a new netif flag
-    (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet
-    device but prevents usage of ARP (so that ethernet_input can be used
-    for PPPoE).
-
-  2010-02-12: Simon Goldschmidt
-  * netif.c: netif_set_link_up/down: only do something if the link state
-    actually changes
-
-  2010-02-12: Simon Goldschmidt/Stephane Lesage
-  * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking
-    connect)
-
-  2010-02-12: Simon Goldschmidt
-  * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h)
-
-  2010-02-09: Simon Goldschmidt
-  * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110
-   (recv() makes receive window update for data that wasn't received by
-    application)
-
-  2010-02-09: Simon Goldschmidt/Stephane Lesage
-  * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out
-    or any netconn_recv() error)
-
-  2010-02-09: Simon Goldschmidt
-  * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets)
-
-  2010-02-09: Simon Goldschmidt
-  * netif.c: For loopback packets, adjust the stats- and snmp-counters
-    for the loopback netif.
-
-  2010-02-08: Simon Goldschmidt
-  * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity
-    since they are not used anywhere else.
-
-  2010-02-08: Simon Goldschmidt (Stéphane Lesage)
-  * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats
-    (patch from bug #28798)
-
-  2010-02-08: Simon Goldschmidt (Stéphane Lesage)
-  * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and
-    another bug when LWIP_RAND() returns zero.
-
-  2010-02-04: Simon Goldschmidt
-  * nearly every file: Use macros defined in ip_addr.h (some of them new)
-    to work with IP addresses (preparation for bug #27352 - Change ip_addr
-    from struct to typedef (u32_t) - and better code).
-
-  2010-01-31: Simon Goldschmidt
-  * netif.c: Don't call the link-callback from netif_set_up/down() since
-    this invalidly retriggers DHCP.
-
-  2010-01-29: Simon Goldschmidt
-  * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the
-    portability file inet.h and its contents from the stack: moved htonX-
-    functions to def.h (and the new def.c - they are not ipv4 dependent),
-    let inet.h depend on ip_addr.h and not the other way round.
-    This fixes bug #28732.
-
-  2010-01-28: Kieran Mansley
-  * tcp.c: Ensure ssthresh >= 2*MSS
-
-  2010-01-27: Simon Goldschmidt
-  * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv
-    callback can lead to accessing unallocated memory. As a consequence,
-    ERR_ABRT means the application has called tcp_abort()!
-
-  2010-01-25: Simon Goldschmidt
-  * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY
-    not implemented in SNMP): write-only or not-accessible are still
-    returned by getnext (though not by get)
-
-  2010-01-24: Simon Goldschmidt
-  * snmp: Renamed the private mib node from 'private' to 'mib_private' to
-    not use reserved C/C++ keywords
-
-  2010-01-23: Simon Goldschmidt
-  * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less
-    than 1 ms
-
-  2010-01-21: Simon Goldschmidt
-  * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called
-    if tcp_enqueue fails) both in raw- and netconn-API
-
-  2010-01-19: Simon Goldschmidt
-  * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp
-
-  2010-01-18: Iordan Neshev/Simon Goldschmidt
-  * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some
-    bugfix backports from 2.4.x.
-
-  2010-01-18: Simon Goldschmidt
-  * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong
-
-  2010-01-17: Simon Goldschmidt
-  * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c):
-    task #10102: "netconn: clean up conn->err threading issues" by adding
-    error return value to struct api_msg_msg
-
-  2010-01-17: Simon Goldschmidt
-  * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept()
-    to return err_t (bugs #27709 and #28087)
-
-  2010-01-14: Simon Goldschmidt
-  * ...: Use typedef for function prototypes throughout the stack.
-
-  2010-01-13: Simon Goldschmidt
-  * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive
-    window = 0) by correctly draining recvmbox/acceptmbox
-
-  2010-01-11: Simon Goldschmidt
-  * pap.c: Fixed bug #13315 (PPP PAP authentication can result in
-    erroneous callbacks) by copying the code from recent pppd
-
-  2010-01-10: Simon Goldschmidt
-  * raw.c: Fixed bug #28506 (raw_bind should filter received packets)
-
-  2010-01-10: Simon Goldschmidt
-  * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)())
-
-  2010-01-08: Simon Goldschmidt
-  * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535)
-
-  2010-01-08: Simon Goldschmidt
-  * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string
-    passed to dns_local_addhost() might be volatile
-
-  2010-01-07: Simon Goldschmidt
-  * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too
-
-  2010-01-06: Simon Goldschmidt
-  * netdb.h: Fixed bug #28496: missing include guards in netdb.h
-
-  2009-12-31: Simon Goldschmidt
-  * many ppp files: Reorganised PPP source code from ucip structure to pppd
-    structure to easily compare our code against the pppd code (around v2.3.1)
-
-  2009-12-27: Simon Goldschmidt
-  * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted
-    unit test
-
-
-(STABLE-1.3.2)
-
-  ++ New features:
-
-  2009-10-27 Simon Goldschmidt/Stephan Lesage
-  * netifapi.c/.h: Added netifapi_netif_set_addr()
-
-  2009-10-07 Simon Goldschmidt/Fabian Koch
-  * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to
-    support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO)
-
-  2009-08-26 Simon Goldschmidt/Simon Kallweit
-  * slipif.c/.h: bug #26397: SLIP polling support
-
-  2009-08-25 Simon Goldschmidt
-  * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN),
-    New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK.
-
-  2009-08-25 Simon Goldschmidt
-  * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*)
-
-  2009-08-24 Jakob Stoklund Olesen
-  * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond
-    to netif_set_link_up().
-
-  2009-08-23 Simon Goldschmidt
-  * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state
-    to a human-readable string.
-
-  ++ Bugfixes:
-
-  2009-12-24: Kieran Mansley
-  * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing
-    (BUG#28241)
-
-  2009-12-06: Simon Goldschmidt
-  * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can
-    be statically allocated (like in ucip)
-
-  2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev)
-  * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT
-
-  2009-12-03: Simon Goldschmidt
-  * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit
-    could have non-zero length
-
-  2009-12-02: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting
-    tcp_input_pcb until after calling the pcb's callbacks
-
-  2009-11-29: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of-
-    sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code
-
-  2009-11-29: Simon Goldschmidt
-  * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by
-    queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty
-
-  2009-11-26: Simon Goldschmidt
-  * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending
-    segment
-
-  2009-11-26: Simon Goldschmidt
-  * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle
-    algorithm at PCB level
-
-  2009-11-22: Simon Goldschmidt
-  * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent
-
-  2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach)
-  * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when
-    reusing time-wait pcb
-
-  2009-11-20: Simon Goldschmidt (patch by Albert Bartel)
-  * sockets.c: Fixed bug #28062: Data received directly after accepting
-    does not wake up select
-
-  2009-11-11: Simon Goldschmidt
-  * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo)
-
-  2009-10-30: Simon Goldschmidt
-  * opt.h: Increased default value for TCP_MSS to 536, updated default
-    value for TCP_WND to 4*TCP_MSS to keep delayed ACK working.
-
-  2009-10-28: Kieran Mansley
-  * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code
-    to follow algorithm from TCP/IP Illustrated
-
-  2009-10-27: Kieran Mansley
-  * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK
-
-  2009-10-25: Simon Goldschmidt
-  * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if
-    pcb->recv is NULL to keep rcv_wnd correct)
-
-  2009-10-25: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state
-
-  2009-10-23: Simon Goldschmidt (David Empson)
-  * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes
-
-  2009-10-21: Simon Goldschmidt
-  * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and
-    trailing 1 byte len (SYN/FIN)
-
-  2009-10-21: Simon Goldschmidt
-  * tcp_out.c: Fixed bug #27315: zero window probe and FIN
-
-  2009-10-19: Simon Goldschmidt
-  * dhcp.c/.h: Minor code simplification (don't store received pbuf, change
-    conditional code to assert where applicable), check pbuf length before
-    testing for valid reply
-
-  2009-10-19: Simon Goldschmidt
-  * dhcp.c: Removed most calls to udp_connect since they aren't necessary
-    when using udp_sendto_if() - always stay connected to IP_ADDR_ANY.
-
-  2009-10-16: Simon Goldschmidt
-  * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop
-    valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is
-    enabled
-
-  2009-10-15: Simon Goldschmidt (Oleg Tyshev)
-  * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit
-
-  2009-10-15: Simon Goldschmidt
-  * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv()
-    timeout
-
-  2009-10-15: Simon Goldschmidt
-  * autoip.c: Fixed bug #27704: autoip starts with wrong address
-    LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead
-    of network byte order
-
-  2009-10-11 Simon Goldschmidt (Jörg Kesten)
-  * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments
-    which are not consecutive when retransmitting unacked segments
-
-  2009-10-09 Simon Goldschmidt
-  * opt.h: Fixed default values of some stats to only be enabled if used
-    Fixes bug #27338: sys_stats is defined when NO_SYS = 1
-
-  2009-08-30 Simon Goldschmidt
-  * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK
-    function" by checking for loopback before calling ip_frag
-
-  2009-08-25 Simon Goldschmidt
-  * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0
-
-  2009-08-23 Simon Goldschmidt
-  * ppp.c: bug #27078: Possible memory leak in pppInit()
-
-  2009-08-23 Simon Goldschmidt
-  * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result
-    is error.
-
-  2009-08-23 Simon Goldschmidt
-  * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF
-    Fixed wrong parenthesis, added check in init.c
-
-  2009-08-23 Simon Goldschmidt
-  * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms
-
-  2009-08-23 Simon Goldschmidt
-  * many ppp files: bug #27267: Added include to string.h where needed
-
-  2009-08-23 Simon Goldschmidt
-  * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian)
-
-
-(STABLE-1.3.1)
-
-  ++ New features:
-
-  2009-05-10 Simon Goldschmidt
-  * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option
-    LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only
-    one pbuf to help MACs that don't support scatter-gather DMA.
-
-  2009-05-09 Simon Goldschmidt
-  * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming
-    ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
-
-  2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen
-  * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive
-    extended info about the currently received packet.
-
-  2009-04-27 Simon Goldschmidt
-  * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1
-
-  2009-04-25 Simon Goldschmidt
-  * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next
-    bigger malloc pool if one is empty (only usable with MEM_USE_POOLS).
-
-  2009-04-21 Simon Goldschmidt
-  * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static
-    hosts table. New configuration options DNS_LOCAL_HOSTLIST and
-    DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined
-    as an external function for lookup.
-
-  2009-04-15 Simon Goldschmidt
-  * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique
-
-  2009-03-31 Kieran Mansley
-  * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for
-    TCP timestamp options, off by default.  Rework tcp_enqueue() to
-    take option flags rather than specified option data
-
-  2009-02-18 Simon Goldschmidt
-  * cc.h: Added printf formatter for size_t: SZT_F
-
-  2009-02-16 Simon Goldschmidt (patch by Rishi Khan)
-  * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast
-    pings
-
-  2009-02-12 Simon Goldschmidt
-  * init.h: Added LWIP_VERSION to get the current version of the stack
-
-  2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler)
-  * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead
-    of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc
-    is otherwise used)
-
-  2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach)
-  * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial()
-  is only used by UDPLITE at present, so conditionalise it.
-
-  2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli)
-  * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP
-    "seed" address. This should reduce AUTOIP conflicts if
-    LWIP_AUTOIP_CREATE_SEED_ADDR is overridden.
-
-  2008-10-02 Jonathan Larmour and Rishi Khan
-  * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking
-    socket.
-
-  2008-06-30 Simon Goldschmidt
-  * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
-    interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows
-    mem_free to run between mem_malloc iterations. Added illegal counter for
-    mem stats.
-
-  2008-06-27 Simon Goldschmidt
-  * stats.h/.c, some other files: patch #6483: stats module improvement:
-    Added defines to display each module's statistic individually, added stats
-    defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
-
-  2008-06-17 Simon Goldschmidt
-  * err.h: patch #6459: Made err_t overridable to use a more efficient type
-    (define LWIP_ERR_T in cc.h)
-
-  2008-06-17 Simon Goldschmidt
-  * slipif.c: patch #6480: Added a configuration option for slipif for symmetry
-    to loopif
-
-  2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
-  * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
-    modified version of patch # 6370: Moved loopif code to netif.c so that
-    loopback traffic is supported on all netifs (all local IPs).
-    Added option to limit loopback packets for each netifs.
-
-
-  ++ Bugfixes:
-  2009-08-12 Kieran Mansley
-  * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when
-    out of window or out of order properly
-
-  2009-08-12 Kieran Mansley
-  * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1
-
-  2009-07-28 Simon Goldschmidt
-  * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s
-
-  2009-07-27 Kieran Mansley
-  * api.h api_msg.h netdb.h sockets.h: add missing #include directives
-
-  2009-07-09 Kieran Mansley
-  * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for
-    recv_avail and don't increment counters until message successfully
-    sent to mbox
-
-  2009-06-25 Kieran Mansley
-  * api_msg.c api.h: BUG26722: initialise netconn write variables 
-    in netconn_alloc
-
-  2009-06-25 Kieran Mansley
-  * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set
-
-  2009-06-25 Kieran Mansley
-  * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct
-    simultaneous close behaviour, and make snd_nxt have the same meaning 
-    as in the RFCs.
-
-  2009-05-12 Simon Goldschmidt
-  * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on
-    arp_table / uses etharp_query" by adding etharp_gratuitous()
-
-  2009-05-12 Simon Goldschmidt
-  * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options
-    to the IP header (used by igmp_ip_output_if)
-
-  2009-05-06 Simon Goldschmidt
-  * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if
-    defined) for SWAP_BYTES_IN_WORD to speed up checksumming.
-
-  2009-05-05 Simon Goldschmidt
-  * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select()
-    to crash
-
-  2009-05-04 Simon Goldschmidt
-  * init.c: snmp was not initialized in lwip_init()
-
-  2009-05-04 Frédéric Bernon
-  * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled.
-
-  2009-05-03 Simon Goldschmidt
-  * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full
-    (and unsent->next == NULL)
-
-  2009-05-02 Simon Goldschmidt
-  * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after
-    1.3.0 in CVS only) - fixes compilation of ppp_oe.c
-
-  2009-05-02 Simon Goldschmidt
-  * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields
-
-  2009-05-01 Simon Goldschmidt
-  * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets
-
-  2009-05-01 Simon Goldschmidt
-  * ppp.c: bug #24228: Memory corruption with PPP and DHCP
-
-  2009-04-29 Frédéric Bernon
-  * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the
-    SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception
-    of broadcast packets even when this option wasn't set. Port maintainers
-    which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h.
-    If you want this option also filter broadcast on recv operations, you also
-    have to set IP_SOF_BROADCAST_RECV=1 in opt.h.
-
-  2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen
-  * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and
-    DHCP/AUTOIP cooperation
-
-  2009-04-25 Simon Goldschmidt, Oleg Tyshev
-  * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd
-    Fixed by sorting the unsent and unacked queues (segments are inserted at the
-    right place in tcp_output and tcp_rexmit).
-
-  2009-04-25 Simon Goldschmidt
-  * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation
-    when debugging": memp_sizes contained the wrong sizes (including sanity
-    regions); memp pools for MEM_USE_POOLS were too small
-
-  2009-04-24 Simon Goldschmidt, Frédéric Bernon
-  * inet.c: patch #6765: Fix a small problem with the last changes (incorrect
-    behavior, with with ip address string not ended by a '\0', a space or a
-    end of line)
-
-  2009-04-19 Simon Goldschmidt
-  * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails,
-    pcb->err is called, not pcb->connected (with an error code).
-
-  2009-04-19 Simon Goldschmidt
-  * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with
-    no-copy-tcpwrite": deallocate option data, only concat segments with same flags
-
-  2009-04-19 Simon Goldschmidt
-  * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated
-    in the header pbuf, not the data pbuf)
-
-  2009-04-18 Simon Goldschmidt
-  * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore()
-
-  2009-04-15 Simon Goldschmidt
-  * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp
-
-  2009-04-15 Simon Goldschmidt
-  * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in
-
-  2009-04-15 Simon Goldschmidt
-  * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function
-    ip_hinted_output() (for smaller code mainly)
-
-  2009-04-15 Simon Goldschmidt
-  * inet.c: patch #6765: Supporting new line characters in inet_aton()
-
-  2009-04-15 Simon Goldschmidt
-  * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option;
-    Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu
-    is big enough in dhcp_start
-
-  2009-04-15 Simon Goldschmidt
-  * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak
-
-  2009-04-15 Simon Goldschmidt
-  * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY
-
-  2009-04-15 Simon Goldschmidt
-  * sockets.c: bug #26121: set_errno can be overridden
-
-  2009-04-09 Kieran Mansley (patch from Luca Ceresoli <lucaceresoli>)
-  * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when
-    LWIP_TCP==0
-
-  2009-04-09 Kieran Mansley (patch from Roy Lee <roylee17>)
-  * tcp.h: Patch#6802 Add do-while-clauses to those function like
-    macros in tcp.h
-
-  2009-03-31 Kieran Mansley
-  * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window
-    updates are calculated and sent (BUG20515)
-
-  * tcp_in.c: cope with SYN packets received during established states,
-    and retransmission of initial SYN.
-
-  * tcp_out.c: set push bit correctly when tcp segments are merged
-
-  2009-03-27 Kieran Mansley
-  * tcp_out.c set window correctly on probes (correcting change made
-    yesterday)
-
-  2009-03-26 Kieran Mansley
-  * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping
-    connections where no reset required (bug #25622)
-
-  * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes 
-    (bug #20779)
-
-  2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach)
-  * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be
-    too small depending on MEM_ALIGNMENT
-
-  2009-02-16 Simon Goldschmidt
-  * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard;
-    converted size argument of netconn_write to 'size_t'
-
-  2009-02-16 Simon Goldschmidt
-  * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host
-    by moving accept callback function pointer to TCP_PCB_COMMON
-
-  2009-02-12 Simon Goldschmidt
-  * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size"
-    option)
-
-  2009-02-11 Simon Goldschmidt
-  * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start)
-
-  2009-02-11 Simon Goldschmidt
-  * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize:
-    RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv())
-
-  2009-02-10 Simon Goldschmidt
-  * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD:
-    Accepts_pending is decrease on a corresponding listen pcb when a connection
-    in state SYN_RCVD is close.
-
-  2009-01-28 Jonathan Larmour
-  * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run
-    out of pool pbufs.
-
-  2008-12-19 Simon Goldschmidt
-  * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 
-
-  2008-12-10 Tamas Somogyi, Frédéric Bernon
-  * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and
-    port uses deleted netbuf.
-
-  2008-10-18 Simon Goldschmidt
-  * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length
-    in tcp_parseopt
-
-  2008-10-15 Simon Goldschmidt
-  * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers
-    by packing the struct ip_reass_helper.
-
-  2008-10-03 David Woodhouse, Jonathan Larmour
-  * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address.
-
-  2008-10-02 Jonathan Larmour
-  * dns.c: Hard-code structure sizes, to avoid issues on some compilers where
-    padding is included.
-
-  2008-09-30 Jonathan Larmour
-  * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an
-    assertion check that addrlen isn't NULL.
-
-  2008-09-30 Jonathan Larmour
-  * tcp.c: Fix bug #24227, wrong error message in tcp_bind.
-
-  2008-08-26 Simon Goldschmidt
-  * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and
-    inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h
-
-  2008-08-14 Simon Goldschmidt
-  * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when
-    tcp_close returns != ERR_OK)
-
-  2008-07-08 Frédéric Bernon
-  * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters
-    in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
-
-  2008-06-24 Jonathan Larmour
-  * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
-    if tcp_seg_copy fails.
-
-  2008-06-17 Simon Goldschmidt
-  * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
-    and created defines for swapping bytes and folding u32 to u16.
-
-  2008-05-30 Kieran Mansley
-  * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
-    rather than rcv_ann_wnd when deciding if packets are in-window.
-    Contributed by <arasmussen@consultant.datasys.swri.edu>
-
-  2008-05-30 Kieran Mansley
-  * mem.h: Fix BUG#23254.  Change macro definition of mem_* to allow
-    passing as function pointers when MEM_LIBC_MALLOC is defined.
-
-  2008-05-09 Jonathan Larmour
-  * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
-    stop it being treated as a fatal error.
-
-  2008-04-15 Simon Goldschmidt
-  * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
-    (flag now cleared)
-
-  2008-03-27 Simon Goldschmidt
-  * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free
-    from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
-    in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs
-    or heap memory from interrupt context
-
-  2008-03-26 Simon Goldschmidt
-  * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote
-    host sent a zero mss as TCP option.
-
-
-(STABLE-1.3.0)
-
-  ++ New features:
-
-  2008-03-10 Jonathan Larmour
-  * inet_chksum.c: Allow choice of one of the sample algorithms to be
-    made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM.
-
-  2008-01-22 Frédéric Bernon
-  * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in 
-    TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names.
-
-  2008-01-14 Frédéric Bernon
-  * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable
-    to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the
-    tcp_recv callback (see rawapi.txt).
-
-  2008-01-14 Frédéric Bernon, Marc Chaland
-  * ip.c: Integrate patch #6369" ip_input : checking before realloc".
-  
-  2008-01-12 Frédéric Bernon
-  * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field
-    netconn::sem per netconn::op_completed like suggested for the task #7490
-    "Add return value to sys_mbox_post".
-
-  2008-01-12 Frédéric Bernon
-  * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE,
-    DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues
-    sizes), like suggested for the task #7490 "Add return value to sys_mbox_post".
-
-  2008-01-10 Frédéric Bernon
-  * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490
-    "Add return value to sys_mbox_post". tcpip_callback is always defined as
-    "blocking" ("block" parameter = 1).
-
-  2008-01-10 Frédéric Bernon
-  * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field
-    netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490
-    "Add return value to sys_mbox_post".
-
-  2008-01-05 Frédéric Bernon
-  * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h:
-    Introduce changes for task #7490 "Add return value to sys_mbox_post" with some
-    modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which
-    indicate the number of pointers query by the mailbox. There is three defines
-    in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the 
-    netconn::acceptmbox. Port maintainers, you can decide to just add this new 
-    parameter in your implementation, but to ignore it to keep the previous behavior.
-    The new sys_mbox_trypost function return a value to know if the mailbox is
-    full or if the message is posted. Take a look to sys_arch.txt for more details.
-    This new function is used in tcpip_input (so, can be called in an interrupt
-    context since the function is not blocking), and in recv_udp and recv_raw.
-
-  2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour
-  * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c,
-    tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the
-    "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add
-    documentation in the rawapi.txt file.
-
-  2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm)
-  * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer
-
-  2007-12-31 Frédéric Bernon, Luca Ceresoli
-  * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets
-    in autoip". The change in etharp_raw could be removed, since all calls to
-    etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be
-    wrong in the future.
-
-  2007-12-30 Frédéric Bernon, Tom Evans
-  * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address
-    Filtering" reported by Tom Evans.
-
-  2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour
-  * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c,
-    sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API
-    applications have to call 'tcp_accepted(pcb)' in their accept callback to
-    keep accepting new connections.
-
-  2007-12-13 Frédéric Bernon
-  * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result"
-    by err_t type. Add a new err_t code "ERR_INPROGRESS".
-
-  2007-12-12 Frédéric Bernon
-  * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles
-    are the one which have ram usage.
-
-  2007-12-05 Frédéric Bernon
-  * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static
-    set of variables (=0) or a local one (=1). In this last case, your port should
-    provide a function "struct hostent* sys_thread_hostent( struct hostent* h)"
-    which have to do a copy of "h" and return a pointer ont the "per-thread" copy.
-
-  2007-12-03 Simon Goldschmidt
-  * ip.c: ip_input: check if a packet is for inp first before checking all other
-    netifs on netif_list (speeds up packet receiving in most cases)
-
-  2007-11-30 Simon Goldschmidt
-  * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access
-    UDP: move a (connected) pcb selected for input to the front of the list of
-    pcbs so that it is found faster next time. Same for RAW pcbs that have eaten
-    a packet.
-
-  2007-11-28 Simon Goldschmidt
-  * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS
-
-  2007-11-25 Simon Goldschmidt
-  * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy
-    algorithm.
-
-  2007-11-24 Simon Goldschmidt
-  * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c
-    to the new file netdb.c; included lwip_getaddrinfo.
-
-  2007-11-21 Simon Goldschmidt
-  * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss
-    based on the MTU of the netif used to send. Enabled by default. Disable by
-    setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492.
-
-  2007-11-19 Frédéric Bernon
-  * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name
-    received match the name query), implement DNS_USES_STATIC_BUF (the place where
-    copy dns payload to parse the response), return an error if there is no place
-    for a new query, and fix some minor problems.
-
-  2007-11-16 Simon Goldschmidt
-  * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c
-    removed files: core/inet.c, core/inet6.c
-    Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into
-    inet and chksum part; changed includes in all lwIP files as appropriate
-
-  2007-11-16 Simon Goldschmidt
-  * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential
-    dns resolver function for netconn api (netconn_gethostbyname) and socket api
-    (gethostbyname/gethostbyname_r).
-
-  2007-11-15 Jim Pettinato, Frédéric Bernon
-  * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name
-    requests with RAW api interface. Initialization is done in lwip_init() with
-    build time options. DNS timer is added in tcpip_thread context. DHCP can set
-    DNS server ip addresses when options are received. You need to set LWIP_DNS=1
-    in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get
-    some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo"
-    list with points to improve.
-
-  2007-11-06 Simon Goldschmidt
-  * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly
-    enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status
-    for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined.
-
-  2007-11-06 Simon Goldschmidt
-  * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include
-    core header files in api.h (ip/tcp/udp/raw.h) to hide the internal
-    implementation from netconn api applications.
-
-  2007-11-03 Frédéric Bernon
-  * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP &
-    RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled
-    by default). Netconn API users can use the netconn_recv_bufsize macro to access
-    it. This is a first release which have to be improve for TCP. Note it used the
-    netconn::recv_avail which need to be more "thread-safe" (note there is already
-    the problem for FIONREAD with lwip_ioctl/ioctlsocket).
-
-  2007-11-01 Frédéric Bernon, Marc Chaland
-  * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c:
-    Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api
-    layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api
-    layer. This option enable to delayed TCP PUSH flag on multiple "write" calls.
-    Note that previous "copy" parameter for "write" APIs is now called "apiflags".
-
-  2007-10-24 Frédéric Bernon
-  * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than 
-    TCP_EVENT_xxx macros to get a code more readable. It could also help to remove
-    some code (like we have talk in "patch #5919 : Create compile switch to remove
-    select code"), but it could be done later.
-
-  2007-10-08 Simon Goldschmidt
-  * many files: Changed initialization: many init functions are not needed any
-    more since we now rely on the compiler initializing global and static
-    variables to zero!
-
-  2007-10-06 Simon Goldschmidt
-  * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY
-    to enqueue the received pbufs so that multiple packets can be reassembled
-    simultaneously and no static reassembly buffer is needed.
-
-  2007-10-05 Simon Goldschmidt
-  * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so
-    all netifs (or ports) can use it.
-
-  2007-10-05 Frédéric Bernon
-  * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the 
-    common function to reduce a little bit the footprint (for all functions using
-    only the "netif" parameter).
-
-  2007-10-03 Frédéric Bernon
-  * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down,
-    netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce
-    a little bit the footprint (for all functions using only the "netif" parameter).
-
-  2007-09-15 Frédéric Bernon
-  * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF
-    option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for
-    netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for
-    IP_MULTICAST_TTL and IP_MULTICAST_IF.
-
-  2007-09-10 Frédéric Bernon
-  * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles
-    even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime()
-    each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can
-    decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but
-    call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime()
-    or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro.
-    This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside
-    snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only
-    when it's queried (any direct call to "sysuptime" is changed by a call to 
-    snmp_get_sysuptime).
-
-  2007-09-09 Frédéric Bernon, Bill Florac
-  * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP,
-    and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags
-    if you want IGMP on an interface. igmp_stop() is now called inside netif_remove().
-    igmp_report_groups() is now called inside netif_set_link_up() (need to have
-    LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait
-    the next query message to receive the matching multicast streams).
-
-  2007-09-08 Frédéric Bernon
-  * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains
-    IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change).
-    Use this new field to access to common pcb fields (ttl, tos, so_options, etc...).
-    Enable to access to these fields with LWIP_TCP=0.
-
-  2007-09-05 Frédéric Bernon
-  * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h,
-    ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option
-    LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default).
-    Be careful, disabling ICMP make your product non-compliant to RFC1122, but
-    help to reduce footprint, and to reduce "visibility" on the Internet.
-
-  2007-09-05 Frédéric Bernon, Bill Florac
-  * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list
-    for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new
-    parameters have to be provided: a task name, and a task stack size. For this
-    one, since it's platform dependant, you could define the best one for you in
-    your lwipopts.h. For port maintainers, you can just add these new parameters
-    in your sys_arch.c file, and but it's not mandatory, use them in your OS
-    specific functions.
-
-  2007-09-05 Frédéric Bernon
-  * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings
-    inside init.c for task #7142 "Sanity check user-configurable values".
-
-  2007-09-04 Frédéric Bernon, Bill Florac
-  * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by
-    memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the
-    value). It will avoid potential fragmentation problems, use a counter to know
-    how many times a group is used on an netif, and free it when all applications
-    leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity
-    check if LWIP_IGMP!=0).
-
-  2007-09-03 Frédéric Bernon
-  * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement".
-    Initialize igmp_mac_filter to NULL in netif_add (this field should be set in
-    the netif's "init" function). Use the "imr_interface" field (for socket layer)
-    and/or the "interface" field (for netconn layer), for join/leave operations.
-    The igmp_join/leavegroup first parameter change from a netif to an ipaddr.
-    This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany).
-
-  2007-08-30 Frédéric Bernon
-  * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions
-    from api/api_lib". Now netbuf API is independant of netconn, and can be used
-    with other API (application based on raw API, or future "socket2" API). Ports
-    maintainers just have to add src/api/netbuf.c in their makefile/projects.
-
-  2007-08-30 Frédéric Bernon, Jonathan Larmour
-  * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check
-    user-configurable values".
-
-  2007-08-29 Frédéric Bernon
-  * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start.
-    igmp_start is call inside netif_add. Now, igmp initialization is in the same
-    spirit than the others modules. Modify some IGMP debug traces.
-
-  2007-08-29 Frédéric Bernon
-  * Add init.h, init.c, Change opt.h, tcpip.c: Task  #7213 "Add a lwip_init function"
-    Add lwip_init function to regroup all modules initializations, and to provide
-    a place to add code for task #7142 "Sanity check user-configurable values".
-    Ports maintainers should remove direct initializations calls from their code,
-    and add init.c in their makefiles. Note that lwip_init() function is called
-    inside tcpip_init, but can also be used by raw api users since all calls are
-    disabled when matching options are disabled. Also note that their is new options
-    in opt.h, you should configure in your lwipopts.h (they are enabled per default).
-
-  2007-08-26 Marc Boucher
-  * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL
-    since they can under certain circumstances be called with an invalid conn
-    pointer after the connection has been closed (and conn has been freed). 
-
-  2007-08-25 Frédéric Bernon (Artem Migaev's Patch)
-  * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up".
-    Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set.
-
-  2007-08-22 Frédéric Bernon
-  * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK
-    to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release.
-
-  2007-08-22 Frédéric Bernon
-  * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT &
-    ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the 
-    name is tcpip_input (we keep the name of 1.2.0 function).
-
-  2007-08-17 Jared Grubb
-  * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool 
-    settings into new memp_std.h and optional user file lwippools.h. This adds
-    more dynamic mempools, and allows the user to create an arbitrary number of
-    mempools for mem_malloc.
-
-  2007-08-16 Marc Boucher
-  * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function;
-    otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely
-    close the connection.
-
-  2007-08-16 Marc Boucher
-  * sockets.c: lwip_accept(): check netconn_peer() error return.
-
-  2007-08-16 Marc Boucher
-  * mem.c, mem.h: Added mem_calloc().
-
-  2007-08-16 Marc Boucher
-  * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT)
-    for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG
-    and starving other message types.
-    Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API
-
-  2007-08-16 Marc Boucher
-  * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf
-    type and flgs (later renamed to flags).
-    Use enum pbuf_flag as pbuf_type.  Renumber PBUF_FLAG_*.
-    Improved lwip_recvfrom().  TCP push now propagated.
-
-  2007-08-16 Marc Boucher
-  * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global
-    provided by etharp.
-
-  2007-08-16 Marc Boucher
-  * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h,
-    etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c:
-    Added PPPoE support and various PPP improvements.
-
-  2007-07-25 Simon Goldschmidt
-  * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial,
-    making netbuf_copy_partial use this function.
-
-  2007-07-25 Simon Goldschmidt
-  * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with
-    2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and
-    other stacks.
-
-  2007-07-13 Jared Grubb (integrated by Frédéric Bernon)
-  * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add
-    a link callback in the netif struct, and functions to handle it. Be carefull
-    for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c)
-    if you want to be sure to be compatible with future changes...
-
-  2007-06-30 Frédéric Bernon
-  * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions.
-
-  2007-06-21 Simon Goldschmidt
-  * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both
-    LWIP_AUTOIP =0 and =1 to remove redundant code.
-
-  2007-06-21 Simon Goldschmidt
-  * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option
-    MEM_USE_POOLS to use 4 pools with different sized elements instead of a
-    heap. This both prevents memory fragmentation and gives a higher speed
-    at the cost of more memory consumption. Turned off by default.
-
-  2007-06-21 Simon Goldschmidt
-  * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of
-    netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into
-    int to be able to send a bigger buffer than 64K with one time (mainly
-    used from lwip_send).
-
-  2007-06-21 Simon Goldschmidt
-  * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write
-    into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too.
-
-  2007-06-21 Simon Goldschmidt
-  * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in
-    netconn_write from api_lib.c to api_msg.c to also prevent multiple context-
-    changes on low memory or empty send-buffer.
-
-  2007-06-18 Simon Goldschmidt
-  * etharp.c, etharp.h: Changed etharp to use a defined hardware address length
-    of 6 to avoid loading netif->hwaddr_len every time (since this file is only
-    used for ethernet and struct eth_addr already had a defined length of 6).
-
-  2007-06-17 Simon Goldschmidt
-  * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets
-    to disable UDP checksum generation on transmit.
-
-  2007-06-13 Frédéric Bernon, Simon Goldschmidt
-  * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid
-    pointers or parameters, and let the possibility to redefined it in cc.h. Use
-    this macro to check "conn" parameter in api_msg.c functions.
-
-  2007-06-11 Simon Goldschmidt
-  * sockets.c, sockets.h: Added UDP lite support for sockets
-
-  2007-06-10 Simon Goldschmidt
-  * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled
-    by default) to switch off UDP-Lite support if not needed (reduces udp.c code
-    size)
-
-  2007-06-09 Dominik Spies (integrated by Frédéric Bernon)
-  * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h:
-    AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and
-    LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt
-    (see TODO mark in the source code).
-
-  2007-06-09 Simon Goldschmidt
-  * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for
-    etharp_output() to match netif->output so etharp_output() can be used
-    directly as netif->output to save one function call.
-
-  2007-06-08 Simon Goldschmidt
-  * netif.h, ethernetif.c, slipif.c, loopif.c: Added define
-    NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables,
-    added initialization of those to ethernetif, slipif and loopif.
-
-  2007-05-18 Simon Goldschmidt
-  * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF
-    (defaulting to off for now) that can be set to 0 to send fragmented
-    packets by passing PBUF_REFs down the stack.
-
-  2007-05-23 Frédéric Bernon
-  * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP
-    connections, such present in patch #5959.
-
-  2007-05-23 Frédéric Bernon
-  * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx
-    code in only one part...
-
-  2007-05-18 Simon Goldschmidt
-  * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp
-    elements to overflow. This is achieved by adding some bytes before and after
-    each pool element (increasing their size, of course), filling them with a
-    prominent value and checking them on freeing the element.
-    Set it to 2 to also check every element in every pool each time memp_malloc()
-    or memp_free() is called (slower but more helpful).
-
-  2007-05-10 Simon Goldschmidt
-  * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for
-    PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce
-    code size.
-
-  2007-05-11 Frédéric Bernon
-  * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c:
-    Include a function pointer instead of a table index in the message to reduce
-    footprint. Disable some part of lwip_send and lwip_sendto if some options are
-    not set (LWIP_TCP, LWIP_UDP, LWIP_RAW).
-
-  2007-05-10 Simon Goldschmidt
-  * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus
-    \ extern "C" {' in all header files. Now you can write your application using
-    the lwIP stack in C++ and simply #include the core files. Note I have left
-    out the netif/ppp/*h header files for now, since I don't know which files are
-    included by applications and which are for internal use only.
-
-  2007-05-09 Simon Goldschmidt
-  * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library
-    memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for
-    situations where some compilers might inline the copy and save a function
-    call. Also replaced all calls to memcpy() with calls to (S)MEMCPY().
-
-  2007-05-08 Simon Goldschmidt
-  * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc())
-    to be overriden in case the C-library malloc implementation is not protected
-    against concurrent access.
-
-  2007-05-04 Simon Goldschmidt (Atte Kojo)
-  * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending
-    multiple packets to the same host.
-
-  2007-05-04 Frédéric Bernon, Jonathan Larmour
-  * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible
-    to corrupt remote addr/port connection state". Reduce problems "not enought memory" with
-    netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between
-    sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function.
-    Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct,
-    these fields are now renamed "addr" & "port".
-
-  2007-04-11 Jonathan Larmour
-  * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new
-    sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return
-    with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro
-    by the port in sys_arch.h if desired.
-
-  2007-04-06 Frédéric Bernon, Simon Goldschmidt
-  * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API
-    allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp
-    clients, using new functions from netifapi.h. Disable as default (no port change to do).
-
-  2007-04-05 Frédéric Bernon
-  * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant.
-
-  2007-04-04 Simon Goldschmidt
-  * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x)
-    use this for and architecture-independent form to tell the compiler you intentionally
-    are not using this variable. Can be overriden in cc.h.
-
-  2007-03-28 Frédéric Bernon
-  * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to
-    define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded
-    string, point on one of your's ethernetif field, or alloc a string you will free yourself).
-    It will be used by DHCP to register a client hostname, but can also be use when you call
-    snmp_set_sysname.
-
-  2007-03-28 Frédéric Bernon
-  * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to 
-    initialize a network interface's flag with. It tell this interface is an ethernet
-    device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility
-    Support for IPv4" section 4.6) when interface is "up" with netif_set_up().
-
-  2007-03-26 Frédéric Bernon, Jonathan Larmour
-  * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build
-    time if you only use PPP or SLIP. The default is enable. Note we don't have to call 
-    etharp_init in your port's initilization sequence if you use tcpip.c, because this call
-    is done in tcpip_init function.
-
-  2007-03-22 Frédéric Bernon
-  * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the
-    new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in
-    your lwipopts.h. More, unused counters are not defined in the stats structs, and not 
-    display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined
-    but never used. Fix msg_in.c with the correct #if test for a stat display.
-
-  2007-03-21 Kieran Mansley
-  * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). 
-    Provides callback on netif up/down state change.
-
-  2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds
-  * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c,
-    ip.c, netif.h, tcpip.c, opt.h:
-    New configuration option LWIP_IGMP to enable IGMP processing. Based on only one 
-    filter per all network interfaces. Declare a new function in netif to enable to
-    control the MAC filter (to reduce lwIP traffic processing).
-
-  2007-03-11 Frédéric Bernon
-  * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can
-    be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this
-    unless you know what you're doing (default are RFC1122 compliant). Note
-    that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds.
-
-  2007-03-08 Frédéric Bernon
-  * tcp.h: Keepalive values can be configured at compile time, but don't change
-    this unless you know what you're doing (default are RFC1122 compliant).
-
-  2007-03-08 Frédéric Bernon
-  * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h:
-    Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO
-    on UDP sockets/netconn.
-
-  2007-03-08 Simon Goldschmidt
-  * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time.
-
-  2007-03-06 Frédéric Bernon
-  * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: 
-    Implement SO_RCVTIMEO on UDP sockets/netconn.
-
-  2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt)
-  * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated
-    on the stack and remove the API msg type from memp
-
-  2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt)
-  * sockets.h, sockets.c: Move socket initialization to new
-    lwip_socket_init() function.
-    NOTE: this changes the API with ports. Ports will have to be
-    updated to call lwip_socket_init() now.
-
-  2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt)
-  * api_lib.c: Use memcpy in netbuf_copy_partial.
-
-
-  ++ Bug fixes:
-
-  2008-03-17 Frédéric Bernon, Ed Kerekes
-  * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have
-    some problems to fill the IP header on some targets, use now the
-    ip.h macros to do it).
-
-  2008-03-13 Frédéric Bernon
-  * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using
-    (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a
-    TCP connection caused a crash. Note that using (lwip_)recvfrom
-    like this is a bit slow and that using (lwip)getpeername is the
-    good lwip way to do it (so, using recv is faster on tcp sockets).
-
-  2008-03-12 Frédéric Bernon, Jonathan Larmour
-  * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's
-    recv_raw() does not consume data", and the ping sample (with
-    LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom
-    returned the IP payload, without the IP header).
-
-  2008-03-04 Jonathan Larmour
-  * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors
-  and/or warnings on some systems where mem_size_t and size_t differ.
-  * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc.
-
-  2008-03-04 Kieran Mansley (contributions by others) 
-  * Numerous small compiler error/warning fixes from contributions to
-    mailing list after 1.3.0 release candidate made.
-
-  2008-01-25 Cui hengbin (integrated by Frédéric Bernon)
-  * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures.
-
-  2008-01-15 Kieran Mansley
-  * tcp_out.c: BUG20511.  Modify persist timer to start when we are
-    prevented from sending by a small send window, not just a zero
-    send window.
-
-  2008-01-09 Jonathan Larmour
-  * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid
-    conflict with Linux system headers.
-
-  2008-01-06 Jonathan Larmour
-  * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP
-    address entirely on receiving a DHCPNAK, and restarting discovery.
-
-  2007-12-21 Simon Goldschmidt
-  * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail
-    is not protected" by using new macros for interlocked access to modify/test
-    netconn->recv_avail.
-
-  2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev)
-  * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state)
-
-  2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm)
-  * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling
-    of silly window avoidance and prevent lwIP from shrinking the window)
-
-  2007-12-04 Simon Goldschmidt
-  * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last
-    data packet was lost): add assert that all segment lists are empty in
-    tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED
-    state from LAST_ACK in tcp_process
-
-  2007-12-02 Simon Goldschmidt
-  * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET
-    If including <sys/time.h> for system-struct timeval, LWIP_TIMEVAL_PRIVATE now
-    has to be set to 0 in lwipopts.h
-
-  2007-12-02 Simon Goldschmidt
-  * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always
-    allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen
-    netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox.
-    This is a fix for thread-safety and allocates all items needed for a netconn
-    when the netconn is created.
-
-  2007-11-30 Simon Goldschmidt
-  * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple
-    netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed
-    to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same
-    port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address)
-
-  2007-11-27 Simon Goldschmidt
-  * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by
-    letting ip_route only use netifs that are up.
-
-  2007-11-27 Simon Goldschmidt
-  * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF
-    and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and
-    sockets block most operations once they have seen a fatal error.
-
-  2007-11-27 Simon Goldschmidt
-  * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the
-    netif to send as an argument (to be able to send on netifs that are down).
-
-  2007-11-26 Simon Goldschmidt
-  * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs
-    arrive out-of-order
-
-  2007-11-21 Simon Goldschmidt
-  * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early
-    Fixed the nagle algorithm; nagle now also works for all raw API applications
-    and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY'
-
-  2007-11-12 Frédéric Bernon
-  * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most
-    of the netconn_peer and netconn_addr processing is done inside tcpip_thread
-    context in do_getaddr.
-
-  2007-11-10 Simon Goldschmidt
-  * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can
-    happen any time). Now the packet simply isn't enqueued when out of memory.
-
-  2007-11-01 Simon Goldschmidt
-  * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or
-    TCP_MSS if that is smaller) as long as no MSS option is received from the
-    remote host.
-
-  2007-11-01 Simon Goldschmidt
-  * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN)
-    is now based on TCP_MSS instead of pcb->mss (on passive open now effectively
-    sending our configured TCP_MSS instead of the one received).
-
-  2007-11-01 Simon Goldschmidt
-  * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was
-    calculated based on the configured TCP_MSS, not on the MSS option received
-    with SYN+ACK.
-
-  2007-10-09 Simon Goldschmidt
-  * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too
-    short and also was generated wrong if checksum coverage != tot_len;
-    receive: checksum was calculated wrong if checksum coverage != tot_len
-
-  2007-10-08 Simon Goldschmidt
-  * mem.c: lfree was not updated in mem_realloc!
-
-  2007-10-07 Frédéric Bernon
-  * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential
-    crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT:
-    this change cause an API breakage for netconn_addr, since a parameter
-    type change. Any compiler should cause an error without any changes in
-    yours netconn_peer calls (so, it can't be a "silent change"). It also
-    reduce a little bit the footprint for socket layer (lwip_getpeername &
-    lwip_getsockname use now a common lwip_getaddrname function since 
-    netconn_peer & netconn_addr have the same parameters).
-
-  2007-09-20 Simon Goldschmidt
-  * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state)
-    by checking  tcp_tw_pcbs also
-
-  2007-09-19 Simon Goldschmidt
-  * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies)
-
-  2007-09-15 Mike Kleshov
-  * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used)
-
-  2007-09-06 Frédéric Bernon
-  * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove
-    it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which
-    already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h"
-    if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h.
-
-  2007-08-30 Frédéric Bernon
-  * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, 
-    and fix some coding style.
-
-  2007-08-28 Frédéric Bernon
-  * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any
-    kind of packets. These packets are considered like Ethernet packets (payload 
-    pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets 
-    are considered like IP packets (payload pointing to iphdr).
-
-  2007-08-27 Frédéric Bernon
-  * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error
-    problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state
-    and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT).
-
-  2007-08-24 Kieran Mansley
-  * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy
-    compiler (Paradigm C++)
-
-  2007-08-09 Frédéric Bernon, Bill Florac
-  * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement.
-    Introduce IGMP_STATS to centralize statistics management.
-
-  2007-08-09 Frédéric Bernon, Bill Florac
-  * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast
-    packet on a udp pcb binded on an netif's IP address, and not on "any".
-
-  2007-08-09 Frédéric Bernon, Bill Florac
-  * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement.
-    This is mainly on using lookup/lookfor, and some coding styles...
-
-  2007-07-26 Frédéric Bernon (and "thedoctor")
-  * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages.
-
-  2007-07-25 Simon Goldschmidt
-  * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if
-    tcp_output fails in tcp_close, the code in do_close_internal gets simpler
-    (tcp_output is called again later from tcp timers).
-
-  2007-07-25 Simon Goldschmidt
-  * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old
-    copy_from_pbuf, which illegally modified the given pbuf.
-
-  2007-07-25 Simon Goldschmidt
-  * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs:
-    changed snd_queuelen++ to snd_queuelen += pbuf_clen(p).
-
-  2007-07-24 Simon Goldschmidt
-  * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the
-    correct state (must be CLOSED).
-
-  2007-07-13 Thomas Taranowski (commited by Jared Grubb)
-  * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed
-    allocation. It now returns NULL.
-
-  2007-07-13 Frédéric Bernon
-  * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in
-    all error cases.
-
-  2007-07-13 Frédéric Bernon
-  * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed,
-    because current code doesn't follow rawapi.txt documentation.
-
-  2007-07-13 Kieran Mansley
-  * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in
-    out of sequence processing of received packets
-
-  2007-07-03 Simon Goldschmidt
-  * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an
-    assumption is made that this pbuf is in one piece (i.e. not chained). These
-    assumptions clash with the possibility of converting to fully pool-based
-    pbuf implementations, where PBUF_RAM pbufs might be chained.
-
-  2007-07-03 Simon Goldschmidt
-  * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems
-    when closing tcp netconns: removed conn->sem, less context switches when
-    closing, both netconn_close and netconn_delete should safely close tcp
-    connections.
-
-  2007-07-02 Simon Goldschmidt
-  * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c,
-    tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off)
-    to cache ARP table indices with each pcb instead of single-entry cache for
-    the complete stack.
-
-  2007-07-02 Simon Goldschmidt
-  * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent
-    warnings when assigning to smaller types.
-
-  2007-06-28 Simon Goldschmidt
-  * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing.
-
-  2007-06-28 Simon Goldschmidt
-  * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if
-    a segment contained chained pbufs)
-
-  2007-06-28 Frédéric Bernon
-  * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute
-    a "pseudo-random" value based on netif's MAC and some autoip fields. It's always
-    possible to define this macro in your own lwipopts.h to always use C library's
-    rand(). Note that autoip_create_rand_addr doesn't use this macro.
-
-  2007-06-28 Frédéric Bernon
-  * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option
-    LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications
-    in api_lib/api_msg (use pointers and not type with table, etc...) 
-
-  2007-06-26 Simon Goldschmidt
-  * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines.
-
-  2007-06-25 Simon Goldschmidt
-  * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload
-    for udp packets with no matching pcb.
-
-  2007-06-25 Simon Goldschmidt
-  * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match
-    could get udp input packets if the remote side matched.
-
-  2007-06-13 Simon Goldschmidt
-  * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get
-    changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0.
-
-  2007-06-13 Simon Goldschmidt
-  * api_msg.c: pcb_new sets conn->err if protocol is not implemented
-    -> netconn_new_..() does not allocate a new connection for unsupported
-    protocols.
-
-  2007-06-13 Frédéric Bernon, Simon Goldschmidt
-  * api_lib.c: change return expression in netconn_addr and netconn_peer, because
-    conn->err was reset to ERR_OK without any reasons (and error was lost)...
-
-  2007-06-13 Frédéric Bernon, Matthias Weisser
-  * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename
-    MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid
-    some macro names collision with some OS macros.
-
-  2007-06-11 Simon Goldschmidt
-  * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0,
-    create checksum over the complete packet. On RX, if it's < 8 (and not 0),
-    discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both
-    UDP & UDP Lite.
-
-  2007-06-11 Srinivas Gollakota & Oleg Tyshev
-  * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags"
-    where TCP flags wasn't initialized in tcp_keepalive.
-
-  2007-06-03 Simon Goldschmidt
-  * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function
-    registered, p->payload was modified without modifying p->len if sending
-    icmp_dest_unreach() (had no negative effect but was definitively wrong).
-
-  2007-06-03 Simon Goldschmidt
-  * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp
-    re-used the input pbuf even if that didn't have enough space to include the
-    link headers. Now the space is tested and a new pbuf is allocated for the
-    echo response packet if the echo request pbuf isn't big enough.
-
-  2007-06-01 Simon Goldschmidt
-  * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread.
-
-  2007-05-23 Frédéric Bernon
-  * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only
-    allocated by do_listen if success) and netconn_accept errors handling. In
-    most of api_lib functions, we replace some errors checkings like "if (conn==NULL)"
-    by ASSERT, except for netconn_delete.
-
-  2007-05-23 Frédéric Bernon
-  * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return
-    an error code if it's impossible to fetch a pbuf on a TCP connection (and not
-    directly close the recvmbox).
-
-  2007-05-22 Simon Goldschmidt
-  * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of
-    bound but unconnected (and non-listening) tcp_pcbs.
-
-  2007-05-22 Frédéric Bernon
-  * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only
-    used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of
-    sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features
-    like "sys_timeout" in their application threads.
-
-  2007-05-22 Frédéric Bernon
-  * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see
-    which parameters are used by which do_xxx function, and to avoid "misusing"
-    parameters (patch #5938).
-
-  2007-05-22 Simon Goldschmidt
-  * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938:
-    changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto
-    is only 8 bits wide. This affects the api, as there, the protocol was
-    u16_t, too.
-
-  2007-05-18 Simon Goldschmidt
-  * memp.c: addition to patch #5913: smaller pointer was returned but
-    memp_memory was the same size -> did not save memory.
-
-  2007-05-16 Simon Goldschmidt
-  * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns
-    != ERR_OK.
-
-  2007-05-16 Simon Goldschmidt
-  * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same
-    as the one of the netif used for sending to prevent sending from old
-    addresses after a netif address gets changed (partly fixes bug #3168).
-
-  2007-05-16 Frédéric Bernon
-  * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work
-    with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in 
-    tcpip_init) because we have to be sure that network interfaces are already
-    added (mac filter is updated only in igmp_init for the moment).
-
-  2007-05-16 Simon Goldschmidt
-  * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls
-    into sys_arch_sem_wait calls to prevent timers from running while waiting
-    for the heap. This fixes bug #19167.
-
-  2007-05-13 Simon Goldschmidt
-  * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines
-    for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from
-    tcp.h to sockets.h.
-
-  2007-05-07 Simon Goldschmidt
-  * mem.c: Another attempt to fix bug #17922.
-
-  2007-05-04 Simon Goldschmidt
-  * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy()
-    implementation so that it can be reused (don't allocate the target
-    pbuf inside pbuf_copy()).
-
-  2007-05-04 Simon Goldschmidt
-  * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem
-    to save a little RAM (next pointer of memp is not used while not in pool).
-
-  2007-05-03 "maq"
-  * sockets.c: Fix ioctl FIONREAD when some data remains from last recv.
-    (patch #3574).
-
-  2007-04-23 Simon Goldschmidt
-  * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results
-    in NULL reference for incoming TCP packets". Loopif has to be configured
-    (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input()
-    (multithreading environments, e.g. netif->input() = tcpip_input()) or
-    putting packets on a list that is fed to the stack by calling loopif_poll()
-    (single-thread / NO_SYS / polling environment where e.g.
-    netif->input() = ip_input).
-
-  2007-04-17 Jonathan Larmour
-  * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold
-    the difference between two u16_t's.
-  * sockets.h: FD_SETSIZE needs to match number of sockets, which is
-    MEMP_NUM_NETCONN in sockets.c right now.
-
-  2007-04-12 Jonathan Larmour
-  * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580).
-
-  2007-04-12 Kieran Mansley
-  * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission
-    timer is reset to fix bug#19434, with help from Oleg Tyshev.
-
-  2007-04-11 Simon Goldschmidt
-  * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than
-    previously thought need to be copied (everything but PBUF_ROM!). Cleaned up
-    pbuf.c: removed functions no needed any more (by etharp).
-
-  2007-04-11 Kieran Mansley
-  * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix
-    "Constant is long" warnings with 16bit compilers.  Contributed by
-    avatar@mmlab.cse.yzu.edu.tw
-
-  2007-04-05 Frédéric Bernon, Jonathan Larmour
-  * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on
-    the mailbox is active". Now, the post is only done during a connect, and do_send,
-    do_write and do_join_leave_group don't do anything if a previous error was signaled.
-
-  2007-04-03 Frédéric Bernon
-  * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output
-    packets. See patch #5834.
-
-  2007-03-30 Frédéric Bernon
-  * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add
-    missing  pcb allocations checking (in do_bind, and for each raw_new). Fix style.
-
-  2007-03-30 Frédéric Bernon
-  * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with
-    others environment defines (these were too "generic").
-
-  2007-03-28 Frédéric Bernon
-  * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call
-    result and can cause a crash. lwip_send now check netbuf_ref result.
-
-  2007-03-28 Simon Goldschmidt
-  * sockets.c Remove "#include <errno.h>" from sockets.c to avoid multiple
-    definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is
-    defined. This is the way it should have been already (looking at
-    doc/sys_arch.txt)
-
-  2007-03-28 Kieran Mansley
-  * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS +
-    IP and TCP headers *and* physical link headers
-
-  2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov)
-  * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause
-    to send some garbage. It is not a definitive solution, but the patch does solve
-    the problem for most cases.
-
-  2007-03-22 Frédéric Bernon
-  * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used).
-
-  2007-03-22 Frédéric Bernon
-  * api_lib.c: somes resources couldn't be freed if there was errors during
-    netconn_new_with_proto_and_callback.
-
-  2007-03-22 Frédéric Bernon
-  * ethernetif.c: update netif->input calls to check return value. In older ports,
-    it's a good idea to upgrade them, even if before, there could be another problem
-    (access to an uninitialized mailbox).
-
-  2007-03-21 Simon Goldschmidt
-  * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed
-    by casting to unsigned).
-
-  2007-03-21 Frédéric Bernon
-  * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from
-    api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a
-    dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call.
-    Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a
-    faster and more reliable communication between api_lib and tcpip.
-
-  2007-03-21 Frédéric Bernon
-  * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0.
-
-  2007-03-21 Frédéric Bernon
-  * api_msg.c, igmp.c, igmp.h: Fix C++ style comments
-
-  2007-03-21 Kieran Mansley
-  * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS +
-    IP and TCP headers
-
-  2007-03-21 Kieran Mansley
-  * Fix all uses of pbuf_header to check the return value.  In some
-    cases just assert if it fails as I'm not sure how to fix them, but
-    this is no worse than before when they would carry on regardless
-    of the failure.
-
-  2007-03-21 Kieran Mansley
-  * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and
-    comment out missing header include in icmp.c
-
-  2007-03-20 Frédéric Bernon
-  * memp.h, stats.c: Fix stats_display function where memp_names table wasn't
-    synchronized with memp.h.
-
-  2007-03-20 Frédéric Bernon
-  * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input,
-    tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with 
-    network interfaces. Also fix a compiler warning.
-
-  2007-03-20 Kieran Mansley
-  * udp.c: Only try and use pbuf_header() to make space for headers if
-    not a ROM or REF pbuf.
-
-  2007-03-19 Frédéric Bernon
-  * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg()
-    and api_msg_post().
-
-  2007-03-19 Frédéric Bernon
-  * Remove unimplemented "memp_realloc" function from memp.h.
-
-  2007-03-11 Simon Goldschmidt
-  * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused
-    memory corruption.
-
-  2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov)
-  * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251
-    (missing `const' qualifier in socket functions), to get more compatible to
-    standard POSIX sockets.
-
-  2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov)
-  * sockets.c: Add asserts inside bind, connect and sendto to check input
-    parameters. Remove excessive set_errno() calls after get_socket(), because
-    errno is set inside of get_socket(). Move last sock_set_errno() inside
-    lwip_close.
-
-  2007-03-09 Simon Goldschmidt
-  * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory
-    was allocated too small.
-
-  2007-03-06 Simon Goldschmidt
-  * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect
-    the stack from concurrent access.
-
-  2007-03-06 Frédéric Bernon, Dmitry Potapov
-  * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy
-    call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input().
-
-  2007-03-06 Simon Goldschmidt
-  * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files
-    if IP_FRAG == 0 and IP_REASSEMBLY == 0
-
-  2007-03-06 Frédéric Bernon, Simon Goldschmidt
-  * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration
-    option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput.
-    Allow to do ARP processing for incoming packets inside tcpip_thread
-    (protecting ARP layer against concurrent access). You can also disable
-    old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0.
-    Older ports have to use tcpip_ethinput.
-
-  2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov)
-  * err.h, err.c: fixed compiler warning "initialization dircards qualifiers
-    from pointer target type"
-
-  2007-03-05 Frédéric Bernon
-  * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES,
-    ETHARP_TRUST_IP_MAC, review SO_REUSE)
-
-  2007-03-04 Frédéric Bernon
-  * api_msg.c: Remove some compiler warnings : parameter "pcb" was never
-    referenced.
-
-  2007-03-04 Frédéric Bernon
-  * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from
-    Dmitry Potapov).
-    The api_msg struct stay on the stack (not moved to netconn struct).
-
-  2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov)
-  * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if
-    SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available)
-    Also fixed cast warning in pbuf_alloc()
-
-  2007-03-04 Simon Goldschmidt
-  * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt
-    existing pbuf chain when enqueuing multiple pbufs to a pending ARP request
-
-  2007-03-03 Frédéric Bernon
-  * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;"
-    It is static, and never used in udp.c except udp_init().
-
-  2007-03-02 Simon Goldschmidt
-  * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from
-    tcpip_thread() to tcpip_init(). This way, raw API connections can be
-    initialized before tcpip_thread is running (e.g. before OS is started)
-
-  2007-03-02 Frédéric Bernon
-  * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call
-    interval.
-
-  2007-02-28 Kieran Mansley 
-  * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved
-    outside the region of the pbuf by pbuf_header()
-
-  2007-02-28 Kieran Mansley 
-  * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero
-    when supplied timeout is also non-zero 
-
-(STABLE-1.2.0)
-
-  2006-12-05 Leon Woestenberg
-  * CHANGELOG: Mention STABLE-1.2.0 release.
-
-  ++ New features:
-
-  2006-12-01 Christiaan Simons
-  * mem.h, opt.h: Added MEM_LIBC_MALLOC option.
-    Note this is a workaround. Currently I have no other options left.
-
-  2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour)
-  * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define
-    to include/lwip/opt.h.
-  * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL.
-    Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h.
-  * opt.h: Add above new options.
-
-  2006-08-18 Christiaan Simons
-  * tcp_{in,out}.c: added SNMP counters.
-  * ipv4/ip.c: added SNMP counters.
-  * ipv4/ip_frag.c: added SNMP counters.
-
-  2006-08-08 Christiaan Simons
-  * etharp.{c,h}: added etharp_find_addr() to read
-    (stable) ethernet/IP address pair from ARP table
-
-  2006-07-14 Christiaan Simons
-  * mib_structs.c: added
-  * include/lwip/snmp_structs.h: added
-  * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct
-
-  2006-07-06 Christiaan Simons
-  * snmp/asn1_{enc,dec}.c added
-  * snmp/mib2.c added
-  * snmp/msg_{in,out}.c added
-  * include/lwip/snmp_asn1.h added
-  * include/lwip/snmp_msg.h added
-  * doc/snmp_agent.txt added
-
-  2006-03-29 Christiaan Simons
-  * inet.c, inet.h: Added platform byteswap support.
-    Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and
-    optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros.
-
-  ++ Bug fixes:
-
-  2006-11-30 Christiaan Simons
-  * dhcp.c: Fixed false triggers of request_timeout.
-
-  2006-11-28 Christiaan Simons
-  * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags.
-
-  2006-10-11 Christiaan Simons
-  * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h:
-    Partially accepted patch #5449 for ANSI C compatibility / build fixes.
-  * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol
-    identifier from 170 to 136 (bug #17574).
-
-  2006-10-10 Christiaan Simons
-  * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice.
-
-  2006-08-17 Christiaan Simons
-  * udp.c: Fixed bug #17200, added check for broadcast
-    destinations for PCBs bound to a unicast address.
-
-  2006-08-07 Christiaan Simons
-  * api_msg.c: Flushing TCP output in do_close() (bug #15926).
-
-  2006-06-27 Christiaan Simons
-  * api_msg.c: Applied patch for cold case (bug #11135).
-    In accept_function() ensure newconn->callback is always initialized.
-
-  2006-06-15 Christiaan Simons
-  * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748),
-    facilitate printing of mem_size_t and u16_t statistics.
-
-  2006-06-14 Christiaan Simons
-  * api_msg.c: Applied patch #5146 to handle allocation failures
-    in accept() by Kevin Lawson.
-
-  2006-05-26 Christiaan Simons
-  * api_lib.c: Removed conn->sem creation and destruction 
-    from netconn_write() and added sys_sem_new to netconn_new_*.
-
-(STABLE-1_1_1)
-
-  2006-03-03  Christiaan Simons
-  * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap
-    access and added pbuf_alloc() return value checks.
-
-  2006-01-01  Leon Woestenberg <leon.woestenberg@gmx.net>
-  * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is
-    now handled by the checksum routine properly.
-
-  2006-02-27  Leon Woestenberg <leon.woestenberg@gmx.net>
-   * pbuf.c: Fix alignment; pbuf_init() would not work unless
-     pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.)
-
-  2005-12-20  Leon Woestenberg <leon.woestenberg@gmx.net>
-  * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch
-    submitted by Mitrani Hiroshi.
-
-  2005-12-15  Christiaan Simons
-  * inet.c: Disabled the added summing routine to preserve code space.
-
-  2005-12-14  Leon Woestenberg <leon.woestenberg@gmx.net>
-  * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
-    Added Curt McDowell's optimized checksumming routine for future
-    inclusion. Need to create test case for unaliged, aligned, odd,
-    even length combination of cases on various endianess machines.
-
-  2005-12-09  Christiaan Simons
-  * inet.c: Rewrote standard checksum routine in proper portable C.
-
-  2005-11-25  Christiaan Simons
-  * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only.
-  * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t,
-    u32_t, s32_t typedefs. This solves most debug word-length assumes.
-
-  2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * inet.c: Fixed unaligned 16-bit access in the standard checksum
-    routine by Peter Jolasson.
-  * slipif.c: Fixed implementation assumption of single-pbuf datagrams.
-
-  2005-02-04 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch.
-  * tcp_{out|in}.c: Applied patch fixing unaligned access.
-
-  2005-01-04 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement.
-
-  2005-01-03 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * udp.c: UDP pcb->recv() was called even when it was NULL.
-
-(STABLE-1_1_0)
-
-  2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * etharp.*: Disabled multiple packets on the ARP queue.
-    This clashes with TCP queueing.
-
-  2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * etharp.*: Fixed race condition from ARP request to ARP timeout.
-    Halved the ARP period, doubled the period counts.
-    ETHARP_MAX_PENDING now should be at least 2. This prevents
-    the counter from reaching 0 right away (which would allow
-    too little time for ARP responses to be received).
-
-  2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * dhcp.c: Decline messages were not multicast but unicast.
-  * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
-    Do not try hard to insert arbitrary packet's source address,
-    etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. 
-    etharp_query() now always DOES call ETHARP_TRY_HARD so that users
-    querying an address will see it appear in the cache (DHCP could
-    suffer from this when a server invalidly gave an in-use address.)
-  * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
-    comparing network addresses (identifiers), not the network masks
-    themselves.
-  * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
-    IP address actually belongs to the network of the given interface.
-
-  2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
-  * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
-
-(STABLE-1_1_0-RC1)
-
-  2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
-  * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
-    even if one is already pending, if the rcv_wnd is above a threshold
-    (currently TCP_WND/2). This avoids waiting for a timer to expire to send a
-    delayed ACK in order to open the window if the stack is only receiving data.
-
-  2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
-  * tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
-
-  2004-08-20 Tony Mountifield <tony@softins.co.uk>
-  * etharp.c: Make sure the first pbuf queued on an ARP entry
-    is properly ref counted.
-
-  2004-07-27 Tony Mountifield <tony@softins.co.uk>
-  * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
-    warnings about comparison.
-  * pbuf.c: Stopped compiler complaining of empty if statement
-    when LWIP_DEBUGF() empty.  Closed an unclosed comment.
-  * tcp.c: Stopped compiler complaining of empty if statement
-    when LWIP_DEBUGF() empty.
-  * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
-  * inet.c: Added a couple of casts to quiet the compiler.
-    No need to test isascii(c) before isdigit(c) or isxdigit(c).
-
-  2004-07-22 Tony Mountifield <tony@softins.co.uk>
-  * inet.c: Made data types consistent in inet_ntoa().
-    Added casts for return values of checksum routines, to pacify compiler.
-  * ip_frag.c, tcp_out.c, sockets.c, pbuf.c
-    Small corrections to some debugging statements, to pacify compiler.
-
-  2004-07-21 Tony Mountifield <tony@softins.co.uk>
-  * etharp.c: Removed spurious semicolon and added missing end-of-comment.
-  * ethernetif.c Updated low_level_output() to match prototype for
-    netif->linkoutput and changed low_level_input() similarly for consistency.
-  * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
-    of raw_recv() in raw.h and so avoid compiler error.
-  * sockets.c: Added trivial (int) cast to keep compiler happier.
-  * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
-
-(STABLE-1_0_0)
-
-  ++ Changes:
-
-  2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
-    your cc.h file defines this either 1 or 0. If non-defined,
-    defaults to 1.
-  * .c: Added <string.h> and <errno.h> includes where used.
-  * etharp.c: Made some array indices unsigned.
-
-  2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * netif.*: Added netif_set_up()/down().
-  * dhcp.c: Changes to restart program flow.
-
-  2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * etharp.c: In find_entry(), instead of a list traversal per candidate, do a
-    single-pass lookup for different candidates. Should exploit locality.
-
-  2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * tcp*.c: Cleaned up source comment documentation for Doxygen processing.
-  * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
-  * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
-    the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
-
-  ++ Bug fixes:
-
-  2004-04-27 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution
-    suggested by Timmy Brolin. Fix for 32-bit processors that cannot access
-    non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix
-    is to prefix the 14-bit Ethernet headers with two padding bytes.
-
-  2004-04-23 Leon Woestenberg <leon.woestenberg@gmx.net>
-  * ip_addr.c: Fix in the ip_addr_isbroadcast() check.
-  * etharp.c: Fixed the case where the packet that initiates the ARP request
-    is not queued, and gets lost. Fixed the case where the packets destination
-    address is already known; we now always queue the packet and perform an ARP
-    request.
-
-(STABLE-0_7_0)
-
-  ++ Bug fixes:
-
-  * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition.
-  * Fixed TCP bug in dequeueing of FIN from out of order segment queue.
-  * Fixed two possible NULL references in rare cases.
-
-(STABLE-0_6_6)
-
-  ++ Bug fixes:
-
-  * Fixed DHCP which did not include the IP address in DECLINE messages.
-
-  ++ Changes:
-
-  * etharp.c has been hauled over a bit.
-
-(STABLE-0_6_5)
-
-  ++ Bug fixes:
-
-  * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
-  * Packets sent from ARP queue had invalid source hardware address.
-
-  ++ Changes:
-
-  * Pass-by ARP requests do now update the cache.
-
-  ++ New features:
-
-  * No longer dependent on ctype.h.
-  * New socket options.
-  * Raw IP pcb support.
-
-(STABLE-0_6_4)
-
-  ++ Bug fixes:
-
-  * Some debug formatters and casts fixed.
-  * Numereous fixes in PPP.
-
-  ++ Changes:
-
-  * DEBUGF now is LWIP_DEBUGF
-  * pbuf_dechain() has been re-enabled.
-  * Mentioned the changed use of CVS branches in README.
-
-(STABLE-0_6_3)
-
-  ++ Bug fixes:
-
-  * Fixed pool pbuf memory leak in pbuf_alloc().
-    Occured if not enough PBUF_POOL pbufs for a packet pbuf chain.
-    Reported by Savin Zlobec.
-
-  * PBUF_POOL chains had their tot_len field not set for non-first
-    pbufs. Fixed in pbuf_alloc().
-
-  ++ New features:
-
-  * Added PPP stack contributed by Marc Boucher
-
-  ++ Changes:
-
-  * Now drops short packets for ICMP/UDP/TCP protocols. More robust.
-
-  * ARP queueuing now queues the latest packet instead of the first.
-    This is the RFC recommended behaviour, but can be overridden in
-    lwipopts.h.
-
-(0.6.2)
-
-  ++ Bugfixes:
-
-  * TCP has been fixed to deal with the new use of the pbuf->ref
-    counter.
-
-  * DHCP dhcp_inform() crash bug fixed.
-
-  ++ Changes:
-
-  * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed
-    pbuf_refresh(). This has sped up pbuf pool operations considerably.
-    Implemented by David Haas.
-
-(0.6.1)
-
-  ++ New features:
-
-  * The packet buffer implementation has been enhanced to support
-    zero-copy and copy-on-demand for packet buffers which have their
-    payloads in application-managed memory.
-    Implemented by David Haas.
-
-    Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy
-    if an outgoing packet can be directly sent on the link, or perform
-    a copy-on-demand when necessary.
-
-    The application can safely assume the packet is sent, and the RAM
-    is available to the application directly after calling udp_send()
-    or similar function.
-
-  ++ Bugfixes:
-
-  * ARP_QUEUEING should now correctly work for all cases, including
-    PBUF_REF.
-    Implemented by Leon Woestenberg.
-
-  ++ Changes:
-
-  * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer
-    to a '0.0.0.0' IP address.
-
-  * The packet buffer implementation is changed. The pbuf->ref counter
-    meaning has changed, and several pbuf functions have been
-    adapted accordingly.
-
-  * netif drivers have to be changed to set the hardware address length field
-    that must be initialized correctly by the driver (hint: 6 for Ethernet MAC).
-    See the contrib/ports/c16x cs8900 driver as a driver example.
-
-  * netif's have a dhcp field that must be initialized to NULL by the driver.
-    See the contrib/ports/c16x cs8900 driver as a driver example.
-
-(0.5.x) This file has been unmaintained up to 0.6.1. All changes are
-  logged in CVS but have not been explained here.
-
-(0.5.3) Changes since version 0.5.2
-
-  ++ Bugfixes:
-
-  * memp_malloc(MEMP_API_MSG) could fail with multiple application
-    threads because it wasn't protected by semaphores.
-
-  ++ Other changes:
-
-  * struct ip_addr now packed.
-
-  * The name of the time variable in arp.c has been changed to ctime
-    to avoid conflicts with the time() function.
-
-(0.5.2) Changes since version 0.5.1
-
-  ++ New features:
-
-  * A new TCP function, tcp_tmr(), now handles both TCP timers.
-
-  ++ Bugfixes:
-
-  * A bug in tcp_parseopt() could cause the stack to hang because of a
-    malformed TCP option.
-
-  * The address of new connections in the accept() function in the BSD
-    socket library was not handled correctly.
-
-  * pbuf_dechain() did not update the ->tot_len field of the tail.
-
-  * Aborted TCP connections were not handled correctly in all
-    situations.
-
-  ++ Other changes:
-
-  * All protocol header structs are now packed.
-
-  * The ->len field in the tcp_seg structure now counts the actual
-    amount of data, and does not add one for SYN and FIN segments.
-
-(0.5.1) Changes since version 0.5.0
-
-  ++ New features:
-
-  * Possible to run as a user process under Linux.
-
-  * Preliminary support for cross platform packed structs.
-
-  * ARP timer now implemented.
-
-  ++ Bugfixes:
-
-  * TCP output queue length was badly initialized when opening
-    connections.
-
-  * TCP delayed ACKs were not sent correctly.
-
-  * Explicit initialization of BSS segment variables.
-
-  * read() in BSD socket library could drop data.
-
-  * Problems with memory alignment.
-
-  * Situations when all TCP buffers were used could lead to
-    starvation.
-
-  * TCP MSS option wasn't parsed correctly.
-
-  * Problems with UDP checksum calculation.
-
-  * IP multicast address tests had endianess problems.
-
-  * ARP requests had wrong destination hardware address.
-
-  ++ Other changes:
-
-  * struct eth_addr changed from u16_t[3] array to u8_t[6].
-
-  * A ->linkoutput() member was added to struct netif.
-
-  * TCP and UDP ->dest_* struct members where changed to ->remote_*.
-
-  * ntoh* macros are now null definitions for big endian CPUs.
-
-(0.5.0) Changes since version 0.4.2
-
-  ++ New features:
-
-  * Redesigned operating system emulation layer to make porting easier.
-
-  * Better control over TCP output buffers.
-
-  * Documenation added.
-
-  ++ Bugfixes:
-
-  * Locking issues in buffer management.
-
-  * Bugfixes in the sequential API.
-
-  * IP forwarding could cause memory leakage. This has been fixed.
-
-  ++ Other changes:
-
-  * Directory structure somewhat changed; the core/ tree has been
-    collapsed.
-
-(0.4.2) Changes since version 0.4.1
-
-  ++ New features:
-
-  * Experimental ARP implementation added.
-
-  * Skeleton Ethernet driver added.
-
-  * Experimental BSD socket API library added.
-
-  ++ Bugfixes:
-
-  * In very intense situations, memory leakage could occur. This has
-    been fixed.
-
-  ++ Other changes:
-
-  * Variables named "data" and "code" have been renamed in order to
-    avoid name conflicts in certain compilers.
-
-  * Variable++ have in appliciable cases been translated to ++variable
-    since some compilers generate better code in the latter case.
-
-(0.4.1) Changes since version 0.4
-
-  ++ New features:
-
-  * TCP: Connection attempts time out earlier than data
-    transmissions. Nagle algorithm implemented. Push flag set on the
-    last segment in a burst.
-
-  * UDP: experimental support for UDP-Lite extensions.
-
-  ++ Bugfixes:
-
-  * TCP: out of order segments were in some cases handled incorrectly,
-    and this has now been fixed. Delayed acknowledgements was broken
-    in 0.4, has now been fixed. Binding to an address that is in use
-    now results in an error. Reset connections sometimes hung an
-    application; this has been fixed.
-
-  * Checksum calculation sometimes failed for chained pbufs with odd
-    lengths. This has been fixed.
-
-  * API: a lot of bug fixes in the API. The UDP API has been improved
-    and tested. Error reporting and handling has been
-    improved. Logical flaws and race conditions for incoming TCP
-    connections has been found and removed.
-
-  * Memory manager: alignment issues. Reallocating memory sometimes
-    failed, this has been fixed.
-
-  * Generic library: bcopy was flawed and has been fixed.
-
-  ++ Other changes:
-
-  * API: all datatypes has been changed from generic ones such as
-    ints, to specified ones such as u16_t. Functions that return
-    errors now have the correct type (err_t).
-
-  * General: A lot of code cleaned up and debugging code removed. Many
-    portability issues have been fixed.
-
-  * The license was changed; the advertising clause was removed.
-
-  * C64 port added.
-
-  * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri
-    Kosunen, Mikael Caleres, and Frits Wilmink for reporting and
-    fixing bugs!
-
-(0.4) Changes since version 0.3.1
-
-  * Memory management has been radically changed; instead of
-    allocating memory from a shared heap, memory for objects that are
-    rapidly allocated and deallocated is now kept in pools. Allocation
-    and deallocation from those memory pools is very fast. The shared
-    heap is still present but is used less frequently.
-
-  * The memory, memory pool, and packet buffer subsystems now support
-    4-, 2-, or 1-byte alignment.
-
-  * "Out of memory" situations are handled in a more robust way.
-
-  * Stack usage has been reduced.
-
-  * Easier configuration of lwIP parameters such as memory usage,
-    TTLs, statistics gathering, etc. All configuration parameters are
-    now kept in a single header file "lwipopts.h".
-
-  * The directory structure has been changed slightly so that all
-    architecture specific files are kept under the src/arch
-    hierarchy.
-
-  * Error propagation has been improved, both in the protocol modules
-    and in the API.
-
-  * The code for the RTXC architecture has been implemented, tested
-    and put to use.
-
-  * Bugs have been found and corrected in the TCP, UDP, IP, API, and
-    the Internet checksum modules.
-
-  * Bugs related to porting between a 32-bit and a 16-bit architecture
-    have been found and corrected.
-
-  * The license has been changed slightly to conform more with the
-    original BSD license, including the advertisement clause.
-
-(0.3.1) Changes since version 0.3
-
-  * Fix of a fatal bug in the buffer management. Pbufs with allocated
-    RAM never returned the RAM when the pbuf was deallocated.
-
-  * TCP congestion control, window updates and retransmissions did not
-    work correctly. This has now been fixed.
-
-  * Bugfixes in the API.
-
-(0.3) Changes since version 0.2
-
-  * New and improved directory structure. All include files are now
-    kept in a dedicated include/ directory.
-
-  * The API now has proper error handling. A new function,
-    netconn_err(), now returns an error code for the connection in
-    case of errors.
-
-  * Improvements in the memory management subsystem. The system now
-    keeps a pointer to the lowest free memory block. A new function,
-    mem_malloc2() tries to allocate memory once, and if it fails tries
-    to free some memory and retry the allocation.
-
-  * Much testing has been done with limited memory
-    configurations. lwIP now does a better job when overloaded.
-
-  * Some bugfixes and improvements to the buffer (pbuf) subsystem.
-
-  * Many bugfixes in the TCP code:
-
-    - Fixed a bug in tcp_close().
-
-    - The TCP receive window was incorrectly closed when out of
-      sequence segments was received. This has been fixed.
-
-    - Connections are now timed-out of the FIN-WAIT-2 state.
-
-    - The initial congestion window could in some cases be too
-      large. This has been fixed.
-
-    - The retransmission queue could in some cases be screwed up. This
-      has been fixed.
-
-    - TCP RST flag now handled correctly.
-
-    - Out of sequence data was in some cases never delivered to the
-      application. This has been fixed.
-
-    - Retransmitted segments now contain the correct acknowledgment
-      number and advertised window.
-
-    - TCP retransmission timeout backoffs are not correctly computed
-      (ala BSD). After a number of retransmissions, TCP now gives up
-      the connection.
-
-  * TCP connections now are kept on three lists, one for active
-    connections, one for listening connections, and one for
-    connections that are in TIME-WAIT. This greatly speeds up the fast
-    timeout processing for sending delayed ACKs.
-
-  * TCP now provides proper feedback to the application when a
-    connection has been successfully set up.
-
-  * More comments have been added to the code. The code has also been
-    somewhat cleaned up.
-
-(0.2) Initial public release.

+ 0 - 33
components/net/lwip-2.0.0/COPYING

@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-

+ 0 - 5
components/net/lwip-2.0.0/FILES

@@ -1,5 +0,0 @@
-src/      - The source code for the lwIP TCP/IP stack.
-doc/      - The documentation for lwIP.
-test/     - Some code to test whether the sources do what they should.
-
-See also the FILES file in each subdirectory.

+ 0 - 100
components/net/lwip-2.0.0/README

@@ -1,100 +0,0 @@
-INTRODUCTION
-
-lwIP is a small independent implementation of the TCP/IP protocol
-suite that has been developed by Adam Dunkels at the Computer and
-Networks Architectures (CNA) lab at the Swedish Institute of Computer
-Science (SICS).
-
-The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
-while still having a full scale TCP. This making lwIP suitable for use
-in embedded systems with tens of kilobytes of free RAM and room for
-around 40 kilobytes of code ROM.
-
-
-FEATURES
-
-  * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
-    multiple network interfaces
-  * ICMP (Internet Control Message Protocol) for network maintenance and debugging
-  * IGMP (Internet Group Management Protocol) for multicast traffic management
-  * MLD (Multicast listener discovery for IPv6). Aims to be compliant with 
-    RFC 2710. No support for MLDv2
-  * ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
-    Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
-    (Address autoconfiguration)
-  * UDP (User Datagram Protocol) including experimental UDP-lite extensions
-  * TCP (Transmission Control Protocol) with congestion control, RTT estimation
-    and fast recovery/fast retransmit
-  * raw/native API for enhanced performance
-  * Optional Berkeley-like socket API
-  * DNS (Domain names resolver)
-
-
-APPLICATIONS
-
-  * HTTP server with SSI and CGI
-  * SNMPv2c agent with MIB compiler (Simple Network Management Protocol)
-  * SNTP (Simple network time protocol)
-  * NetBIOS name service responder
-  * MDNS (Multicast DNS) responder
-  * iPerf server implementation
-
-
-LICENSE
-
-lwIP is freely available under a BSD license.
-
-
-DEVELOPMENT
-
-lwIP has grown into an excellent TCP/IP stack for embedded devices,
-and developers using the stack often submit bug fixes, improvements,
-and additions to the stack to further increase its usefulness.
-
-Development of lwIP is hosted on Savannah, a central point for
-software development, maintenance and distribution. Everyone can
-help improve lwIP by use of Savannah's interface, Git and the
-mailing list. A core team of developers will commit changes to the
-Git source tree.
-
-The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
-contributions (such as platform ports) are in the 'contrib' Git module.
-
-See doc/savannah.txt for details on Git server access for users and
-developers.
-
-The current Git trees are web-browsable:
-  http://git.savannah.gnu.org/cgit/lwip.git
-  http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
-
-Submit patches and bugs via the lwIP project page:
-  http://savannah.nongnu.org/projects/lwip/
-
-Continuous integration builds (GCC, clang):
-  https://travis-ci.org/yarrick/lwip-merged
-
-
-DOCUMENTATION
-
-Self documentation of the source code is regularly extracted from the current
-Git sources and is available from this web page:
-  http://www.nongnu.org/lwip/
-
-There is now a constantly growing wiki about lwIP at
-  http://lwip.wikia.com/wiki/LwIP_Wiki
-
-Also, there are mailing lists you can subscribe at
-  http://savannah.nongnu.org/mail/?group=lwip
-plus searchable archives:
-  http://lists.nongnu.org/archive/html/lwip-users/
-  http://lists.nongnu.org/archive/html/lwip-devel/
-
-lwIP was originally written by Adam Dunkels:
-  http://dunkels.com/adam/
-
-Reading Adam's papers, the files in docs/, browsing the source code
-documentation and browsing the mailing list archives is a good way to
-become familiar with the design of lwIP.
-
-Adam Dunkels <adam@sics.se>
-Leon Woestenberg <leon.woestenberg@gmx.net>

+ 0 - 81
components/net/lwip-2.0.0/SConscript

@@ -1,81 +0,0 @@
-from building import *
-
-src = Split("""
-src/arch/sys_arch.c
-src/api/api_lib.c
-src/api/api_msg.c
-src/api/err.c
-src/api/netbuf.c
-src/api/netdb.c
-src/api/netifapi.c
-src/api/sockets.c
-src/api/tcpip.c
-src/core/def.c
-src/core/dns.c
-src/core/inet_chksum.c
-src/core/init.c
-src/core/ip.c
-src/core/memp.c
-src/core/netif.c
-src/core/pbuf.c
-src/core/raw.c
-src/core/stats.c
-src/core/sys.c
-src/core/tcp.c
-src/core/tcp_in.c
-src/core/tcp_out.c
-src/core/timeouts.c
-src/core/udp.c
-src/netif/ethernet.c
-src/netif/ethernetif.c
-src/netif/lowpan6.c
-src/netif/slipif.c
-""")
-
-ipv4_src = Split("""
-src/core/ipv4/autoip.c
-src/core/ipv4/dhcp.c
-src/core/ipv4/etharp.c
-src/core/ipv4/icmp.c
-src/core/ipv4/igmp.c
-src/core/ipv4/ip4.c
-src/core/ipv4/ip4_addr.c
-src/core/ipv4/ip4_frag.c
-""")
-
-ipv6_src = Split("""
-src/core/ipv6/dhcp6.c
-src/core/ipv6/ethip6.c
-src/core/ipv6/icmp6.c
-src/core/ipv6/inet6.c
-src/core/ipv6/ip6.c
-src/core/ipv6/ip6_addr.c
-src/core/ipv6/ip6_frag.c
-src/core/ipv6/mld6.c
-src/core/ipv6/nd6.c
-""")
-
-snmp_src = Glob("src/apps/snmp/*.c")
-
-ppp_src = Glob("src/netif/ppp/*.c") + Glob("src/netif/ppp/polarssl/*c")
-
-src = src + ipv4_src
-
-# The set of source files associated with this SConscript file.
-path = [GetCurrentDir() + '/src',
-    GetCurrentDir() + '/src/include',
-    GetCurrentDir() + '/src/include/ipv4',
-    GetCurrentDir() + '/src/arch/include',
-    GetCurrentDir() + '/src/include/netif']
-
-if GetDepend(['RT_LWIP_SNMP']):
-    src += snmp_src
-    path += [GetCurrentDir() + '/src/apps/snmp']
-
-if GetDepend(['RT_LWIP_PPP']):
-    src += ppp_src
-    path += [GetCurrentDir() + '/src/netif/ppp']
-
-group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP200'], CPPPATH = path)
-
-Return('group')

+ 0 - 228
components/net/lwip-2.0.0/UPGRADING

@@ -1,228 +0,0 @@
-This file lists major changes between release versions that require
-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
-with newer versions.
-
-
-(git master)
-
-  * [Enter new changes just after this line - do not remove this line]
-
-  * TODO
-
-(2.0.0)
-
-  ++ Application changes:
-
-  * 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
-    has to be set "up" before starting the DHCP client
-  * Added IPv6 support (dual-stack or IPv4/IPv6 only)
-  * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
-  * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
-    supports SNMPv2c (experimental v3 support)
-  * Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
-
-  +++ Raw API:
-    * 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
-
-  +++ Socket API:
-    * Added an implementation for posix sendmsg()
-    * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
-
-  ++ Port changes
-
-  +++ new files:
-    * MANY new and moved files! 
-    * Added src/Filelists.mk for use in Makefile projects
-    * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
-      to let abc.h only contain the actual application programmer's API
-
-  +++ sys layer:
-    * 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
-      open to priority inversion, so this is not recommended any more)
-    * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
-      instead of using one per netconn (these semaphores are used even with core locking
-      enabled as some longer lasting functions like big writes still need to delay)
-    * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
-      in def.h (to be overridden in cc.h) instead of config 
-      options for netbiosns, httpd, dns, etc. ...
-    * New abstraction for hton* and ntoh* functions in def.h.
-      To override them, use the following in cc.h: 
-      #define lwip_htons(x) <your_htons>
-      #define lwip_htonl(x) <your_htonl>
-
-  +++ new options:
-     * TODO
-
-  +++ new pools:
-     * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
-       that share memp.c code but do not have to be made global via lwippools.h
-     * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
-     * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
-       is now available
-
-  * Signature of LWIP_HOOK_VLAN_SET macro was changed
-
-  * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
-    or to move buffers to dedicated memory using compiler attributes
-
-  * Standard C headers are used to define sized types and printf formatters
-    (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
-    does not support these)
-
-
-  ++ Major bugfixes/improvements
-
-  * Added IPv6 support (dual-stack or IPv4/IPv6 only)
-  * Major rewrite of PPP (incl. keep-up with apache pppd)
-    see doc/ppp.txt for an upgrading how-to
-  * Major rewrite of SNMP (incl. MIB parser)
-  * Fixed timing issues that might have lead to losing a DHCP lease
-  * Made rx processing path more robust against crafted errors
-  * TCP window scaling support
-  * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
-  * made DNS client more robust
-  * support PBUF_REF for RX packets
-  * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
-    threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
-  * Moved and reordered stats (mainly memp/mib2)
-
-(1.4.0)
-
-  ++ Application changes:
-
-  * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
-    compatibility to old applications, but will be removed in the future).
-
-  * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
-
-  +++ Raw API:
-    * Changed the semantics of tcp_close() (since it was rather a
-      shutdown before): Now the application does *NOT* get any calls to the recv
-      callback (aside from NULL/closed) after calling tcp_close()
-
-    * When calling tcp_abort() from a raw API TCP callback function,
-      make sure you return ERR_ABRT to prevent accessing unallocated memory.
-      (ERR_ABRT now means the applicaiton has called tcp_abort!)
-
-  +++ Netconn API:
-    * Changed netconn_receive() and netconn_accept() to return
-      err_t, not a pointer to new data/netconn.
-
-  +++ Socket API:
-    * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
-      now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
-
-    * Added a minimal version of posix fctl() to have a
-      standardised way to set O_NONBLOCK for nonblocking sockets.
-
-  +++ all APIs:
-    * correctly implemented SO(F)_REUSEADDR
-
-  ++ Port changes
-
-  +++ new files:
-
-    * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
-
-    * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
-      the actual application programmer's API
-  
-    * Separated timer implementation from sys.h/.c, moved to timers.h/.c;
-      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).
-
-  +++ sys layer:
-
-    * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
-      sys_sem_t;
-
-    * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
-
-    * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
-      binary semaphores instead of mutexes - as before)
-
-  +++ new options:
-
-     * Don't waste memory when chaining segments, added option TCP_OVERSIZE to
-       prevent creating many small pbufs when calling tcp_write with many small
-       blocks of data. Instead, pbufs are allocated larger than needed and the
-       space is used for later calls to tcp_write.
-
-     * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
-       in tcp_write/udp_send.
-
-    * Added an additional option LWIP_ETHERNET to support ethernet without ARP
-      (necessary for pure PPPoE)
-
-    * 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
-      declaration.
-
-    * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
-
-  +++ new pools:
-
-     * Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
-       so MEMP_NUM_NETDB has to be set accordingly.
-
-     * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
-       MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
-
-     * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
-       to be set accordingly.
-
-     * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
-       has to be set accordingly
-
-  * Integrated loopif into netif.c - loopif does not have to be created by the
-    port any more, just define LWIP_HAVE_LOOPIF to 1.
-
-  * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
-    in cc.h, e.g. used by igmp)
-
-  * Added printf-formatter X8_F to printf u8_t as hex
-
-  * 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
-
-  * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
-    with user-allocated structs instead of calling mem_malloc
-
-  * Added const char* name to mem- and memp-stats for easier debugging.
-
-  * Calculate the TCP/UDP checksum while copying to only fetch data once:
-    Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
-
-  * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
-    more than one pcb.
-
-  * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
-    off any more, if this is set to 0, only one packet (the most recent one) is
-    queued (like demanded by RFC 1122).
-
-  
-  ++ Major bugfixes/improvements
-
-  * 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

+ 0 - 9
components/net/lwip-2.0.0/doc/FILES

@@ -1,9 +0,0 @@
-doxygen/       - Configuration files and scripts to create the lwIP doxygen source
-                 documentation (found at http://www.nongnu.org/lwip/)
-
-savannah.txt   - How to obtain the current development source code.
-contrib.txt    - How to contribute to lwIP as a developer.
-rawapi.txt     - The documentation for the core API of lwIP.
-                 Also provides an overview about the other APIs and multithreading.
-sys_arch.txt   - The documentation for a system abstraction layer of lwIP.
-ppp.txt        - Documentation of the PPP interface for lwIP.

+ 0 - 117
components/net/lwip-2.0.0/doc/NO_SYS_SampleCode.c

@@ -1,117 +0,0 @@
-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 */
-  }
-}

+ 0 - 58
components/net/lwip-2.0.0/doc/contrib.txt

@@ -1,58 +0,0 @@
-1 Introduction
-
-This document describes some guidelines for people participating
-in lwIP development.
-
-2 How to contribute to lwIP
-
-Here is a short list of suggestions to anybody working with lwIP and 
-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
-to fixes or questions might often come late. Hopefully the bug and patch tracking 
-features of Savannah help us not lose users' input.
-
-2.1 Source code style:
-
-1. do not use tabs.
-2. indentation is two spaces per level (i.e. per tab).
-3. end debug messages with a trailing newline (\n).
-4. one space between keyword and opening bracket.
-5. no space between function and opening bracket.
-6. one space and no newline before opening curly braces of a block.
-7. closing curly brace on a single line.
-8. spaces surrounding assignment and comparisons.
-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.
-
-2.2 Source code documentation style:
-
-1. JavaDoc compliant and Doxygen compatible.
-2. Function documentation above functions in .c files, not .h files.
-   (This forces you to synchronize documentation and implementation.)
-3. Use current documentation style as further reference.
- 
-2.3 Bug reports and patches:
-
-1. Make sure you are reporting bugs or send patches against the latest
-   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
-   bugtracker at Savannah.
-3. If you have a fix put the patch on Savannah. If it is a patch that affects
-   both core and arch specific stuff please separate them so that the core can
-   be applied separately while leaving the other patch 'open'. The preferred way
-   is to NOT touch archs you can't test and let maintainers take care of them.
-   This is a good way to see if they are used at all - the same goes for unix
-   netifs except tapif.
-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.
-   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
-   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
-   if it's not to the point and long :) so the chances for it to be applied are greater. 
-
-2.4 Platform porters:
-
-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
-   can also ask for Git access to submit and maintain your port in the contrib Git module.

+ 0 - 1
components/net/lwip-2.0.0/doc/doxygen/generate.bat

@@ -1 +0,0 @@
-doxygen lwip.Doxyfile

+ 0 - 1
components/net/lwip-2.0.0/doc/doxygen/generate.sh

@@ -1 +0,0 @@
-doxygen lwip.Doxyfile

+ 0 - 2505
components/net/lwip-2.0.0/doc/doxygen/lwip.Doxyfile

@@ -1,2505 +0,0 @@
-# Doxyfile 1.8.11
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a double hash (##) is considered a comment and is placed in
-# front of the TAG it is preceding.
-#
-# All text after a single hash (#) is considered a comment and will be ignored.
-# The format is:
-# TAG = value [value, ...]
-# For lists, items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (\" \").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
-# The default value is: UTF-8.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
-# double-quotes, unless you are using Doxywizard) that should identify the
-# project for which the documentation is generated. This name is used in the
-# title of most generated pages and in a few other places.
-# The default value is: My Project.
-
-PROJECT_NAME           = "lwIP 2.0.0"
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
-# could be handy for archiving the generated documentation or if some version
-# control system is used.
-
-PROJECT_NUMBER         = "lwIP 2.0.0"
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer a
-# quick idea about the purpose of the project. Keep the description short.
-
-PROJECT_BRIEF          = Lightweight IP stack
-
-# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
-# in the documentation. The maximum height of the logo should not exceed 55
-# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
-# the logo to the output directory.
-
-PROJECT_LOGO           =
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
-# into which the generated documentation will be written. If a relative path is
-# entered, it will be relative to the location where doxygen was started. If
-# left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = output
-
-# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
-# option can be useful when feeding doxygen a huge amount of source files, where
-# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
-# The default value is: NO.
-
-CREATE_SUBDIRS         = NO
-
-# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
-# characters to appear in the names of generated files. If set to NO, non-ASCII
-# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
-# U+3044.
-# The default value is: NO.
-
-ALLOW_UNICODE_NAMES    = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
-# The default value is: English.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
-# descriptions after the members that are listed in the file and class
-# documentation (similar to Javadoc). Set to NO to disable this.
-# The default value is: YES.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
-# description of a member or function before the detailed description
-#
-# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-# The default value is: YES.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator that is
-# used to form the text in various listings. Each string in this list, if found
-# as the leading text of the brief description, will be stripped from the text
-# and the result, after processing the whole list, is used as the annotated
-# text. Otherwise, the brief description is used as-is. If left blank, the
-# following values are used ($name is automatically replaced with the name of
-# the entity):The $name class, The $name widget, The $name file, is, provides,
-# specifies, contains, represents, a, an and the.
-
-ABBREVIATE_BRIEF       = "The $name class       " \
-                         "The $name widget       " \
-                         "The $name file       " \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# doxygen will generate a detailed section even if there is only a brief
-# description.
-# The default value is: NO.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-# The default value is: NO.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
-# before files name in the file list and in the header files. If set to NO the
-# shortest path that makes the file name unique will be used
-# The default value is: YES.
-
-FULL_PATH_NAMES        = YES
-
-# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
-# Stripping is only done if one of the specified strings matches the left-hand
-# part of the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the path to
-# strip.
-#
-# Note that you can specify absolute paths here, but also relative paths, which
-# will be relative from the directory where doxygen is started.
-# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-
-STRIP_FROM_PATH        = ../../
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
-# path mentioned in the documentation of a class, which tells the reader which
-# header file to include in order to use a class. If left blank only the name of
-# the header file containing the class definition is used. Otherwise one should
-# specify the list of include paths that are normally passed to the compiler
-# using the -I flag.
-
-STRIP_FROM_INC_PATH    =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
-# less readable) file names. This can be useful is your file systems doesn't
-# support long names like on DOS, Mac, or CD-ROM.
-# The default value is: NO.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
-# first line (until the first dot) of a Javadoc-style comment as the brief
-# description. If set to NO, the Javadoc-style will behave just like regular Qt-
-# style comments (thus requiring an explicit @brief command for a brief
-# description.)
-# The default value is: NO.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
-# line (until the first dot) of a Qt-style comment as the brief description. If
-# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
-# requiring an explicit \brief command for a brief description.)
-# The default value is: NO.
-
-QT_AUTOBRIEF           = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
-# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
-# a brief description. This used to be the default behavior. The new default is
-# to treat a multi-line C++ comment block as a detailed description. Set this
-# tag to YES if you prefer the old behavior instead.
-#
-# Note that setting this tag to YES also means that rational rose comments are
-# not recognized any more.
-# The default value is: NO.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
-# documentation from any documented member that it re-implements.
-# The default value is: YES.
-
-INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
-# page for each member. If set to NO, the documentation of a member will be part
-# of the file/class/namespace that contains it.
-# The default value is: NO.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
-# uses this value to replace tabs by spaces in code fragments.
-# Minimum value: 1, maximum value: 16, default value: 4.
-
-TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that act as commands in
-# the documentation. An alias has the form:
-# name=value
-# For example adding
-# "sideeffect=@par Side Effects:\n"
-# will allow you to put the command \sideeffect (or @sideeffect) in the
-# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
-
-ALIASES                =
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST              =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C. For
-# instance, some of the names that are used will be different. The list of all
-# members will be omitted, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_FOR_C  = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
-# Python sources only. Doxygen will then generate output that is more tailored
-# for that language. For instance, namespaces will be presented as packages,
-# qualified scopes will look different, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources. Doxygen will then generate output that is tailored for Fortran.
-# The default value is: NO.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for VHDL.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given
-# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
-#
-# Note: For files without extension you can use no_extension as a placeholder.
-#
-# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
-
-EXTENSION_MAPPING      =
-
-# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
-# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you can
-# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
-# case of backward compatibilities issues.
-# The default value is: YES.
-
-MARKDOWN_SUPPORT       = YES
-
-# When enabled doxygen tries to link words that correspond to documented
-# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by putting a % sign in front of the word or
-# globally by setting AUTOLINK_SUPPORT to NO.
-# The default value is: YES.
-
-AUTOLINK_SUPPORT       = YES
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should set this
-# tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string);
-# versus func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-# The default value is: NO.
-
-BUILTIN_STL_SUPPORT    = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-# The default value is: NO.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
-# will parse them like normal C++ but will assume all classes use public instead
-# of private inheritance when no explicit protection keyword is present.
-# The default value is: NO.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES will make
-# doxygen to replace the get and set methods by a property in the documentation.
-# This will only work if the methods are indeed getting or setting a simple
-# type. If this is not the case, or you want to show the methods anyway, you
-# should set this option to NO.
-# The default value is: YES.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-# The default value is: NO.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# If one adds a struct or class to a group and this option is enabled, then also
-# any nested class or struct is added to the same group. By default this option
-# is disabled and one has to add nested compounds explicitly via \ingroup.
-# The default value is: NO.
-
-GROUP_NESTED_COMPOUNDS = NO
-
-# Set the SUBGROUPING tag to YES to allow class member groups of the same type
-# (for instance a group of public functions) to be put as a subgroup of that
-# type (e.g. under the Public Functions section). Set it to NO to prevent
-# subgrouping. Alternatively, this can be done per class using the
-# \nosubgrouping command.
-# The default value is: YES.
-
-SUBGROUPING            = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
-# are shown inside the group in which they are included (e.g. using \ingroup)
-# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
-# and RTF).
-#
-# Note that this feature does not work in combination with
-# SEPARATE_MEMBER_PAGES.
-# The default value is: NO.
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
-# with only public data fields or simple typedef fields will be shown inline in
-# the documentation of the scope in which they are defined (i.e. file,
-# namespace, or group documentation), provided this scope is documented. If set
-# to NO, structs, classes, and unions are shown on a separate page (for HTML and
-# Man pages) or section (for LaTeX and RTF).
-# The default value is: NO.
-
-INLINE_SIMPLE_STRUCTS  = NO
-
-# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
-# enum is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically be
-# useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-# The default value is: NO.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
-# cache is used to resolve symbols given their name and scope. Since this can be
-# an expensive process and often the same symbol appears multiple times in the
-# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
-# doxygen will become slower. If the cache is too large, memory is wasted. The
-# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
-# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
-# symbols. At the end of a run doxygen will report the cache usage and suggest
-# the optimal cache size from a speed point of view.
-# Minimum value: 0, maximum value: 9, default value: 0.
-
-LOOKUP_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
-# documentation are documented, even if no documentation was available. Private
-# class members and static file members will be hidden unless the
-# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
-# Note: This will also disable the warnings about undocumented members that are
-# normally produced when WARNINGS is set to YES.
-# The default value is: NO.
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
-# be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
-# scope will be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PACKAGE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
-# included in the documentation.
-# The default value is: NO.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO,
-# only classes defined in header files are included. Does not have any effect
-# for Java sources.
-# The default value is: YES.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# This flag is only useful for Objective-C code. If set to YES, local methods,
-# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO, only methods in the interface are
-# included.
-# The default value is: NO.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base name of
-# the file that contains the anonymous namespace. By default anonymous namespace
-# are hidden.
-# The default value is: NO.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
-# undocumented members inside documented classes or files. If set to NO these
-# members will be included in the various overviews, but no documentation
-# section is generated. This option has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_MEMBERS     = YES
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO, these classes will be included in the various overviews. This option
-# has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_CLASSES     = YES
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
-# The default value is: NO.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO, these
-# blocks will be appended to the function's detailed documentation block.
-# The default value is: NO.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation that is typed after a
-# \internal command is included. If the tag is set to NO then the documentation
-# will be excluded. Set it to YES to include the internal documentation.
-# The default value is: NO.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
-
-CASE_SENSE_NAMES       = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES, the
-# scope will be hidden.
-# The default value is: NO.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
-# append additional text to a page's title, such as Class Reference. If set to
-# YES the compound reference will be hidden.
-# The default value is: NO.
-
-HIDE_COMPOUND_REFERENCE= NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
-# the files that are included by a file in the documentation of that file.
-# The default value is: YES.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
-# grouped member an include statement to the documentation, telling the reader
-# which file to include in order to use the member.
-# The default value is: NO.
-
-SHOW_GROUPED_MEMB_INC  = NO
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
-# files with double quotes in the documentation rather than with sharp brackets.
-# The default value is: NO.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
-# documentation for inline members.
-# The default value is: YES.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
-# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order.
-# The default value is: YES.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
-# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order. Note that
-# this will also influence the order of the classes in the class list.
-# The default value is: NO.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
-# (brief and detailed) documentation of class members so that constructors and
-# destructors are listed first. If set to NO the constructors will appear in the
-# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
-# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
-# member documentation.
-# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
-# detailed member documentation.
-# The default value is: NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
-# of group names into alphabetical order. If set to NO the group names will
-# appear in their defined order.
-# The default value is: NO.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
-# fully-qualified names, including namespaces. If set to NO, the class list will
-# be sorted only by class name, not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the alphabetical
-# list.
-# The default value is: NO.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
-# type resolution of all parameters of a function it will reject a match between
-# the prototype and the implementation of a member function even if there is
-# only one candidate or it is obvious which candidate to choose by doing a
-# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
-# accept a match between prototype and implementation in such cases.
-# The default value is: NO.
-
-STRICT_PROTO_MATCHING  = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
-# list. This list is created by putting \todo commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TODOLIST      = NO
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
-# list. This list is created by putting \test commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
-# list. This list is created by putting \bug commands in the documentation.
-# The default value is: YES.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
-# the deprecated list. This list is created by putting \deprecated commands in
-# the documentation.
-# The default value is: YES.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional documentation
-# sections, marked by \if <section_label> ... \endif and \cond <section_label>
-# ... \endcond blocks.
-
-ENABLED_SECTIONS       =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
-# initial value of a variable or macro / define can have for it to appear in the
-# documentation. If the initializer consists of more lines than specified here
-# it will be hidden. Use a value of 0 to hide initializers completely. The
-# appearance of the value of individual variables and macros / defines can be
-# controlled using \showinitializer or \hideinitializer command in the
-# documentation regardless of this setting.
-# Minimum value: 0, maximum value: 10000, default value: 30.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES, the
-# list will mention the files that were used to generate the documentation.
-# The default value is: YES.
-
-SHOW_USED_FILES        = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
-# will remove the Files entry from the Quick Index and from the Folder Tree View
-# (if specified).
-# The default value is: YES.
-
-SHOW_FILES             = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
-# page. This will remove the Namespaces entry from the Quick Index and from the
-# Folder Tree View (if specified).
-# The default value is: YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command command input-file, where command is the value of the
-# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
-# by doxygen. Whatever the program writes to standard output is used as the file
-# version. For an example see the documentation.
-
-FILE_VERSION_FILTER    =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option. You can
-# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
-#
-# Note that if you run doxygen from a directory containing a file called
-# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
-# tag is left empty.
-
-LAYOUT_FILE            =
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
-# the reference definitions. This must be a list of .bib files. The .bib
-# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
-# For LaTeX the style of the bibliography can be controlled using
-# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. See also \cite for info how to create references.
-
-CITE_BIB_FILES         =
-
-#---------------------------------------------------------------------------
-# Configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated to
-# standard output by doxygen. If QUIET is set to YES this implies that the
-# messages are off.
-# The default value is: NO.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
-# this implies that the warnings are on.
-#
-# Tip: Turn warnings on while writing the documentation.
-# The default value is: YES.
-
-WARNINGS               = YES
-
-# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
-# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
-# will automatically be disabled.
-# The default value is: YES.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
-# The default value is: YES.
-
-WARN_IF_DOC_ERROR      = YES
-
-# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
-# are documented, but have no documentation for their parameters or return
-# value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation.
-# The default value is: NO.
-
-WARN_NO_PARAMDOC       = NO
-
-# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
-# The default value is: NO.
-
-WARN_AS_ERROR          = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that doxygen
-# can produce. The string should contain the $file, $line, and $text tags, which
-# will be replaced by the file and line number from which the warning originated
-# and the warning text. Optionally the format may contain $version, which will
-# be replaced by the version of the file (if it could be obtained via
-# FILE_VERSION_FILTER)
-# The default value is: $file:$line: $text.
-
-WARN_FORMAT            = "$file:$line: $text       "
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning and error
-# messages should be written. If left blank the output is written to standard
-# error (stderr).
-
-WARN_LOGFILE           =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag is used to specify the files and/or directories that contain
-# documented source files. You may enter file names like myfile.cpp or
-# directories like /usr/src/myproject. Separate the files or directories with
-# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
-# Note: If this tag is empty the current directory is searched.
-
-INPUT                  = main_page.h ../../src
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
-# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
-# The default value is: UTF-8.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# read by doxygen.
-#
-# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
-# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
-# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
-# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
-
-FILE_PATTERNS          = *.c \
-                         *.cc \
-                         *.cxx \
-                         *.cpp \
-                         *.c++ \
-                         *.java \
-                         *.ii \
-                         *.ixx \
-                         *.ipp \
-                         *.i++ \
-                         *.inl \
-                         *.h \
-                         *.hh \
-                         *.hxx \
-                         *.hpp \
-                         *.h++ \
-                         *.idl \
-                         *.odl \
-                         *.inc \
-                         *.m \
-                         *.mm \
-                         *.dox
-
-# The RECURSIVE tag can be used to specify whether or not subdirectories should
-# be searched for input files as well.
-# The default value is: NO.
-
-RECURSIVE              = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-#
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE                = ../../src/include/netif/ppp/polarssl
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-# The default value is: NO.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories.
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories use the pattern */test/*
-
-EXCLUDE_SYMBOLS        =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or directories
-# that contain example code fragments that are included (see the \include
-# command).
-
-EXAMPLE_PATH           = ../ ../../
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank all
-# files are included.
-
-EXAMPLE_PATTERNS       = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude commands
-# irrespective of the value of the RECURSIVE tag.
-# The default value is: NO.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or directories
-# that contain images that are to be included in the documentation (see the
-# \image command).
-
-IMAGE_PATH             =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command:
-#
-# <filter> <input-file>
-#
-# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
-# name of an input file. Doxygen will then use the output that the filter
-# program writes to standard output. If FILTER_PATTERNS is specified, this tag
-# will be ignored.
-#
-# Note that the filter must not add or remove lines; it is applied before the
-# code is scanned, but not when the output code is generated. If lines are added
-# or removed, the anchors will not be placed correctly.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-INPUT_FILTER           =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form: pattern=filter
-# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
-# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
-# patterns match the file name, INPUT_FILTER is applied.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-FILTER_PATTERNS        =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will also be used to filter the input files that are used for
-# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
-# The default value is: NO.
-
-FILTER_SOURCE_FILES    = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
-# it is also possible to disable source filtering for a specific pattern using
-# *.ext= (so without naming a filter).
-# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-
-FILTER_SOURCE_PATTERNS =
-
-# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
-# is part of the input, its contents will be placed on the main page
-# (index.html). This can be useful if you have a project on for instance GitHub
-# and want to reuse the introduction page also for the doxygen output.
-
-USE_MDFILE_AS_MAINPAGE = main_page.h
-
-#---------------------------------------------------------------------------
-# Configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
-# generated. Documented entities will be cross-referenced with these sources.
-#
-# Note: To get rid of all source code in the generated output, make sure that
-# also VERBATIM_HEADERS is set to NO.
-# The default value is: NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body of functions,
-# classes and enums directly into the documentation.
-# The default value is: NO.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
-# special comment blocks from generated source code fragments. Normal C, C++ and
-# Fortran comments will always remain visible.
-# The default value is: YES.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
-# The default value is: NO.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES then for each documented function
-# all documented entities called/used by that function will be listed.
-# The default value is: NO.
-
-REFERENCES_RELATION    = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES then the hyperlinks from functions in REFERENCES_RELATION and
-# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
-# link to the documentation.
-# The default value is: YES.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
-# source code will show a tooltip with additional information such as prototype,
-# brief description and links to the definition and documentation. Since this
-# will make the HTML file larger and loading of large files a bit slower, you
-# can opt to disable this feature.
-# The default value is: YES.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-SOURCE_TOOLTIPS        = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code will
-# point to the HTML generated by the htags(1) tool instead of doxygen built-in
-# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
-# 4.8.6 or higher.
-#
-# To use it do the following:
-# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
-# - Make sure the INPUT points to the root of the source tree
-# - Run doxygen as normal
-#
-# Doxygen will invoke htags (and that will in turn invoke gtags), so these
-# tools must be available from the command line (i.e. in the search path).
-#
-# The result: instead of the source browser generated by doxygen, the links to
-# source code will now point to the output of htags.
-# The default value is: NO.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
-# verbatim copy of the header file for each class for which an include is
-# specified. Set to NO to disable this.
-# See also: Section \class.
-# The default value is: YES.
-
-VERBATIM_HEADERS       = NO
-
-# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
-# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
-# cost of reduced performance. This can be particularly helpful with template
-# rich C++ code for which doxygen's built-in parser lacks the necessary type
-# information.
-# Note: The availability of this option depends on whether or not doxygen was
-# generated with the -Duse-libclang=ON option for CMake.
-# The default value is: NO.
-
-CLANG_ASSISTED_PARSING = NO
-
-# If clang assisted parsing is enabled you can provide the compiler with command
-# line options that you would normally use when invoking the compiler. Note that
-# the include paths will already be set by doxygen for the files and directories
-# specified with INPUT and INCLUDE_PATH.
-# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-
-CLANG_OPTIONS          =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
-# compounds will be generated. Enable this if the project contains a lot of
-# classes, structs, unions or interfaces.
-# The default value is: YES.
-
-ALPHABETICAL_INDEX     = NO
-
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-IGNORE_PREFIX          =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
-# The default value is: YES.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
-# generated HTML page (for example: .htm, .php, .asp).
-# The default value is: .html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
-# each generated HTML page. If the tag is left blank doxygen will generate a
-# standard header.
-#
-# To get valid HTML the header file that includes any scripts and style sheets
-# that doxygen needs, which is dependent on the configuration options used (e.g.
-# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
-# default header using
-# doxygen -w html new_header.html new_footer.html new_stylesheet.css
-# YourConfigFile
-# and then modify the file new_header.html. See also section "Doxygen usage"
-# for information on how to generate the default header that doxygen normally
-# uses.
-# Note: The header is subject to change so you typically have to regenerate the
-# default header when upgrading to a newer version of doxygen. For a description
-# of the possible markers and block names see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_HEADER            =
-
-# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
-# generated HTML page. If the tag is left blank doxygen will generate a standard
-# footer. See HTML_HEADER for more information on how to generate a default
-# footer and what special commands can be used inside the footer. See also
-# section "Doxygen usage" for information on how to generate the default footer
-# that doxygen normally uses.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FOOTER            =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
-# sheet that is used by each HTML page. It can be used to fine-tune the look of
-# the HTML output. If left blank doxygen will generate a default style sheet.
-# See also section "Doxygen usage" for information on how to generate the style
-# sheet that doxygen normally uses.
-# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
-# it is more robust and this tag (HTML_STYLESHEET) will in the future become
-# obsolete.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_STYLESHEET        =
-
-# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# cascading style sheets that are included after the standard style sheets
-# created by doxygen. Using this option one can overrule certain style aspects.
-# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefore more robust against future updates.
-# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_STYLESHEET  =
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
-# files will be copied as-is; there are no commands or markers available.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_FILES       =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the style sheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
-# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
-# purple, and 360 is red again.
-# Minimum value: 0, maximum value: 359, default value: 220.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_HUE    = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
-# value of 255 will produce the most vivid colors.
-# Minimum value: 0, maximum value: 255, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_SAT    = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
-# luminance component of the colors in the HTML output. Values below 100
-# gradually make the output lighter, whereas values above 100 make the output
-# darker. The value divided by 100 is the actual gamma applied, so 80 represents
-# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
-# change the gamma.
-# Minimum value: 40, maximum value: 240, default value: 80.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_GAMMA  = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting this
-# to YES can help to show when doxygen was last run and thus if the
-# documentation is up to date.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_TIMESTAMP         = NO
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_DYNAMIC_SECTIONS  = NO
-
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
-# shown in the various tree structured indices initially; the user can expand
-# and collapse entries dynamically later on. Doxygen will expand the tree to
-# such a level that at most the specified number of entries are visible (unless
-# a fully collapsed tree already exceeds this amount). So setting the number of
-# entries 1 will produce a full collapsed tree by default. 0 is a special value
-# representing an infinite number of entries and will result in a full expanded
-# tree by default.
-# Minimum value: 0, maximum value: 9999, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files will be
-# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_DOCSET        = NO
-
-# This tag determines the name of the docset feed. A documentation feed provides
-# an umbrella under which multiple documentation sets from a single provider
-# (such as a company or product suite) can be grouped.
-# The default value is: Doxygen generated docs.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# This tag specifies a string that should uniquely identify the documentation
-# set bundle. This should be a reverse domain-name style string, e.g.
-# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-# The default value is: org.doxygen.Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
-
-# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
-# The default value is: Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_NAME  = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
-# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
-# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
-#
-# The HTML Help Workshop contains a compiler that can convert all HTML output
-# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
-# files are now used as the Windows 98 help format, and will replace the old
-# Windows help format (.hlp) on all Windows platforms in the future. Compressed
-# HTML files also contain an index, a table of contents, and you can search for
-# words in the documentation. The HTML workshop also contains a viewer for
-# compressed HTML files.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_HTMLHELP      = NO
-
-# The CHM_FILE tag can be used to specify the file name of the resulting .chm
-# file. You can add a path in front of the file if the result should not be
-# written to the html output directory.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_FILE               = lwip.chm
-
-# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler (hhc.exe). If non-empty,
-# doxygen will try to run the HTML help compiler on the generated index.hhp.
-# The file has to be specified with full path.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-HHC_LOCATION           =
-
-# The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-GENERATE_CHI           = NO
-
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
-# and project file content.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_INDEX_ENCODING     =
-
-# The BINARY_TOC flag controls whether a binary table of contents is generated
-# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
-# enables the Previous and Next buttons.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members to
-# the table of contents of the HTML help documentation and to the tree view.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
-# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
-# (.qch) of the generated HTML documentation.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
-# the file name of the resulting .qch file. The path specified is relative to
-# the HTML output folder.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QCH_FILE               =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
-# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
-# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
-# The default value is: doc.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
-# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_NAME   =
-
-# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_ATTRS  =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_SECT_FILTER_ATTRS  =
-
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHG_LOCATION           =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
-# generated, together with the HTML files, they form an Eclipse help plugin. To
-# install this plugin and make it available under the help contents menu in
-# Eclipse, the contents of the directory containing the HTML and XML files needs
-# to be copied into the plugins directory of eclipse. The name of the directory
-# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
-# After copying Eclipse needs to be restarted before the help appears.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the Eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have this
-# name. Each documentation set should have its own identifier.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# If you want full control over the layout of the generated HTML pages it might
-# be necessary to disable the index and replace it with your own. The
-# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
-# of each HTML page. A value of NO enables the index and the value YES disables
-# it. Since the tabs in the index contain the same information as the navigation
-# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-DISABLE_INDEX          = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information. If the tag
-# value is set to YES, a side panel will be generated containing a tree-like
-# index structure (just like the one that is generated for HTML Help). For this
-# to work a browser that supports JavaScript, DHTML, CSS and frames is required
-# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_TREEVIEW      = YES
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
-# doxygen will group on one line in the generated HTML documentation.
-#
-# Note that a value of 0 will completely suppress the enum values from appearing
-# in the overview section.
-# Minimum value: 0, maximum value: 20, default value: 4.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
-# to set the initial width (in pixels) of the frame in which the tree is shown.
-# Minimum value: 0, maximum value: 1500, default value: 250.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-TREEVIEW_WIDTH         = 250
-
-# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
-# external symbols imported via tag files in a separate window.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-EXT_LINKS_IN_WINDOW    = NO
-
-# Use this tag to change the font size of LaTeX formulas included as images in
-# the HTML documentation. When you change the font size after a successful
-# doxygen run you need to manually remove any form_*.png images from the HTML
-# output directory to force them to be regenerated.
-# Minimum value: 8, maximum value: 50, default value: 10.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_FONTSIZE       = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_TRANSPARENT    = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
-# installed or if you want to formulas look prettier in the HTML output. When
-# enabled you may also need to install MathJax separately and configure the path
-# to it using the MATHJAX_RELPATH option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-USE_MATHJAX            = NO
-
-# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
-# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
-# The default value is: HTML-CSS.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_FORMAT         = HTML-CSS
-
-# When MathJax is enabled you need to specify the location relative to the HTML
-# output directory using the MATHJAX_RELPATH option. The destination directory
-# should contain the MathJax.js script. For instance, if the mathjax directory
-# is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
-# Content Delivery Network so you can quickly see the result without installing
-# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
-# extension names that should be enabled during MathJax rendering. For example
-# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_EXTENSIONS     =
-
-# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
-# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
-# example see the documentation.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_CODEFILE       =
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
-# the HTML output. The underlying search engine uses javascript and DHTML and
-# should work on any modern browser. Note that when using HTML help
-# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
-# there is already a search function so this one should typically be disabled.
-# For large projects the javascript based search engine can be slow, then
-# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
-# search using the keyboard; to jump to the search box use <access key> + S
-# (what the <access key> is depends on the OS and browser, but it is typically
-# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
-# key> to jump into the search results window, the results can be navigated
-# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
-# the search. The filter options can be selected when the cursor is inside the
-# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
-# to select a filter and <Enter> or <escape> to activate or cancel the filter
-# option.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-SEARCHENGINE           = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
-# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
-# setting. When disabled, doxygen will generate a PHP script for searching and
-# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
-# and searching needs to be provided by external tools. See the section
-# "External Indexing and Searching" for details.
-# The default value is: NO.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SERVER_BASED_SEARCH    = NO
-
-# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
-# script for searching. Instead the search results are written to an XML file
-# which needs to be processed by an external indexer. Doxygen will invoke an
-# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
-# search results.
-#
-# Doxygen ships with an example indexer (doxyindexer) and search engine
-# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
-#
-# See the section "External Indexing and Searching" for details.
-# The default value is: NO.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTERNAL_SEARCH        = NO
-
-# The SEARCHENGINE_URL should point to a search engine hosted by a web server
-# which will return the search results when EXTERNAL_SEARCH is enabled.
-#
-# Doxygen ships with an example indexer (doxyindexer) and search engine
-# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SEARCHENGINE_URL       =
-
-# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
-# search data is written to a file for indexing by an external tool. With the
-# SEARCHDATA_FILE tag the name of this file can be specified.
-# The default file is: searchdata.xml.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SEARCHDATA_FILE        = searchdata.xml
-
-# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
-# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
-# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
-# projects and redirect the results back to the right project.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTERNAL_SEARCH_ID     =
-
-# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
-# projects other than the one defined by this configuration file, but that are
-# all added to the same external search index. Each project needs to have a
-# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
-# to a relative location where the documentation can be found. The format is:
-# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTRA_SEARCH_MAPPINGS  =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
-# The default value is: YES.
-
-GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: latex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked.
-#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
-# index for LaTeX.
-# The default file is: makeindex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
-# documents. This may be useful for small projects and may help to save some
-# trees in general.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used by the
-# printer.
-# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
-# 14 inches) and executive (7.25 x 10.5 inches).
-# The default value is: a4.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-PAPER_TYPE             = a4wide
-
-# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. The package can be specified just
-# by its name or with the correct syntax as to be used with the LaTeX
-# \usepackage command. To get the times font for instance you can specify :
-# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
-# To use the option intlimits with the amsmath package you can specify:
-# EXTRA_PACKAGES=[intlimits]{amsmath}
-# If left blank no extra packages will be included.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-EXTRA_PACKAGES         =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
-#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
-# string, for the replacement values of the other commands the user is referred
-# to HTML_HEADER.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_HEADER           =
-
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
-# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_FOOTER           =
-
-# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# LaTeX style sheets that are included after the standard style sheets created
-# by doxygen. Using this option one can overrule certain style aspects. Doxygen
-# will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list).
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EXTRA_STYLESHEET =
-
-# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the LATEX_OUTPUT output
-# directory. Note that the files will be copied as-is; there are no commands or
-# markers available.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EXTRA_FILES      =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
-# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
-# contain links (just like the HTML output) instead of page references. This
-# makes the output suitable for online browsing using a PDF viewer.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-PDF_HYPERLINKS         = NO
-
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-USE_PDFLATEX           = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
-# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_BATCHMODE        = NO
-
-# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
-# index chapters (such as File Index, Compound Index, etc.) in the output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_HIDE_INDICES     = NO
-
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE      = NO
-
-# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
-# The default value is: plain.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_BIB_STYLE        = plain
-
-# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
-# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_TIMESTAMP        = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
-# RTF output is optimized for Word 97 and may not look too pretty with other RTF
-# readers/editors.
-# The default value is: NO.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: rtf.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
-# documents. This may be useful for small projects and may help to save some
-# trees in general.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
-# contain hyperlink fields. The RTF file will contain links (just like the HTML
-# output) instead of page references. This makes the output suitable for online
-# browsing using Word or some other Word compatible readers that support those
-# fields.
-#
-# Note: WordPad (write) and others do not support links.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
-#
-# See also section "Doxygen usage" for information on how to generate the
-# default style sheet that doxygen normally uses.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_STYLESHEET_FILE    =
-
-# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_EXTENSIONS_FILE    =
-
-# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
-# with syntax highlighting in the RTF output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_SOURCE_CODE        = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
-# classes and files.
-# The default value is: NO.
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it. A directory man3 will be created inside the directory specified by
-# MAN_OUTPUT.
-# The default directory is: man.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to the generated
-# man pages. In case the manual section does not start with a number, the number
-# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
-# optional.
-# The default value is: .3.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_EXTENSION          = .3
-
-# The MAN_SUBDIR tag determines the name of the directory created within
-# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
-# MAN_EXTENSION with the initial . removed.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_SUBDIR             =
-
-# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
-# will generate one additional man file for each entity documented in the real
-# man page(s). These additional files only source the real man page, but without
-# them the man command would be unable to find the correct page.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
-# captures the structure of the code including all documentation.
-# The default value is: NO.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: xml.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_OUTPUT             = xml
-
-# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
-# listings (including syntax highlighting and cross-referencing information) to
-# the XML output. Note that enabling this will significantly increase the size
-# of the XML output.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# Configuration options related to the DOCBOOK output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
-# that can be used to generate PDF.
-# The default value is: NO.
-
-GENERATE_DOCBOOK       = NO
-
-# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
-# front of it.
-# The default directory is: docbook.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_OUTPUT         = docbook
-
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
-#---------------------------------------------------------------------------
-# Configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
-# AutoGen Definitions (see http://autogen.sf.net) file that captures the
-# structure of the code including all documentation. Note that this feature is
-# still experimental and incomplete at the moment.
-# The default value is: NO.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
-# file that captures the structure of the code including all documentation.
-#
-# Note that this feature is still experimental and incomplete at the moment.
-# The default value is: NO.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
-# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
-# output from the Perl module output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
-# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO, the
-# size of the Perl module output will be much smaller and Perl will parse it
-# just the same.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file are
-# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
-# so different doxyrules.make files included by the same Makefile don't
-# overwrite each other's variables.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
-# C-preprocessor directives found in the sources and include files.
-# The default value is: YES.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
-# in the source code. If set to NO, only conditional compilation will be
-# performed. Macro expansion can be done in a controlled way by setting
-# EXPAND_ONLY_PREDEF to YES.
-# The default value is: NO.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-MACRO_EXPANSION        = YES
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
-# the macro expansion is limited to the macros specified with the PREDEFINED and
-# EXPAND_AS_DEFINED tags.
-# The default value is: NO.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES, the include files in the
-# INCLUDE_PATH will be searched if a #include is found.
-# The default value is: YES.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by the
-# preprocessor.
-# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-
-INCLUDE_PATH           = ../../src/include
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will be
-# used.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-INCLUDE_FILE_PATTERNS  = *.h
-
-# The PREDEFINED tag can be used to specify one or more macro names that are
-# defined before the preprocessor is started (similar to the -D option of e.g.
-# gcc). The argument of the tag is a list of macros of the form: name or
-# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
-# is assumed. To prevent a macro definition from being undefined via #undef or
-# recursively expanded use the := operator instead of the = operator.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-PREDEFINED             = __DOXYGEN__=1 \
-                         NO_SYS=0 \
-                         SYS_LIGHTWEIGHT_PROT=1 \
-                         LWIP_TCPIP_CORE_LOCKING=1 \
-                         LWIP_IPV4=1 \
-                         LWIP_IPV6=1 \
-                         LWIP_ICMP=1 \
-                         LWIP_RAW=1 \
-                         LWIP_DHCP=1 \
-                         LWIP_UDPLITE=1 \
-                         LWIP_UDP=1 \
-                         LWIP_IGMP=1 \
-                         LWIP_TCP=1 \
-                         TCP_LISTEN_BACKLOG=1 \
-                         LWIP_SNMP=1 \
-                         SNMP_USE_NETCONN=1 \
-                         SNMP_USE_RAW=1 \
-                         MIB2_STATS=1 \
-                         LWIP_MDNS_RESPONDER=1 \
-                         MEMP_OVERFLOW_CHECK=0 \
-                         MEMP_SANITY_CHECK=1 \
-                         LWIP_ARP=1 \
-                         LWIP_HAVE_LOOPIF=1 \
-                         LWIP_NETIF_HOSTNAME=1 \
-                         LWIP_NETIF_API=1 \
-                         LWIP_NETIF_CALLBACK=1 \
-                         LWIP_NETIF_STATUS_CALLBACK=1 \
-                         LWIP_NETIF_REMOVE_CALLBACK=1 \
-                         LWIP_NETIF_LINK_CALLBACK=1 \
-                         LWIP_NUM_NETIF_CLIENT_DATA=1 \
-                         ENABLE_LOOPBACK=1 \
-                         LWIP_AUTOIP=1 \
-                         ARP_QUEUEING=1 \
-                         LWIP_STATS=1 \
-                         MEM_USE_POOLS=0 \
-                         LWIP_DNS=1 \
-                         LWIP_SOCKET=1 \
-                         LWIP_NETCONN=1 \
-                         IP_SOF_BROADCAST=1 \
-                         IP_SOF_BROADCAST_RECV=1 \
-                         LWIP_NETIF_API=1 \
-                         LWIP_SO_SNDTIMEO=1 \
-                         LWIP_SO_RCVBUF=1 \
-                         LWIP_SO_LINGER=1 \
-                         SO_REUSE=1 \
-                         SO_REUSE_RXTOALL=1 \
-                         LWIP_HAVE_SLIPIF=1 \
-                         LWIP_6LOWPAN=1
- 
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
-# tag can be used to specify a list of macro names that should be expanded. The
-# macro definition that is found in the sources will be used. Use the PREDEFINED
-# tag if you want to use a different macro definition that overrules the
-# definition found in the source code.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-EXPAND_AS_DEFINED      =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all references to function-like macros that are alone on a line, have
-# an all uppercase name, and do not end with a semicolon. Such function macros
-# are typically used for boiler-plate code, and will confuse the parser if not
-# removed.
-# The default value is: YES.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-SKIP_FUNCTION_MACROS   = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES tag can be used to specify one or more tag files. For each tag
-# file the location of the external documentation should be added. The format of
-# a tag file without this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where loc1 and loc2 can be relative or absolute paths or URLs. See the
-# section "Linking to external documentation" for more information about the use
-# of tag files.
-# Note: Each tag file must have a unique name (where the name does NOT include
-# the path). If a tag file is not located in the directory in which doxygen is
-# run, you must also specify the path to the tagfile here.
-
-TAGFILES               =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
-# tag file that is based on the input files it reads. See section "Linking to
-# external documentation" for more information about the usage of tag files.
-
-GENERATE_TAGFILE       =
-
-# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
-# the class index. If set to NO, only the inherited external classes will be
-# listed.
-# The default value is: NO.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will be
-# listed.
-# The default value is: YES.
-
-EXTERNAL_GROUPS        = YES
-
-# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
-# the related pages index. If set to NO, only the current project's pages will
-# be listed.
-# The default value is: YES.
-
-EXTERNAL_PAGES         = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of 'which perl').
-# The default file (with absolute path) is: /usr/bin/perl.
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS         = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see:
-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH            =
-
-# You can include diagrams made with dia in doxygen documentation. Doxygen will
-# then run dia to produce the diagram and insert it in the documentation. The
-# DIA_PATH tag allows you to specify the directory where the dia binary resides.
-# If left empty dia is assumed to be found in the default search path.
-
-DIA_PATH               =
-
-# If set to YES the inheritance and collaboration graphs will hide inheritance
-# and usage relations if the target is undocumented or is not a class.
-# The default value is: YES.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz (see:
-# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
-# Bell Labs. The other options in this section have no effect if this option is
-# set to NO
-# The default value is: YES.
-
-HAVE_DOT               = NO
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
-# to run in parallel. When set to 0 doxygen will base this on the number of
-# processors available in the system. You can set it explicitly to a value
-# larger than 0 to get control over the balance between CPU load and processing
-# speed.
-# Minimum value: 0, maximum value: 32, default value: 0.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_NUM_THREADS        = 0
-
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTNAME           = Helvetica
-
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTSIZE           = 10
-
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTPATH           =
-
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
-# graph for each documented class showing the direct and indirect implementation
-# dependencies (inheritance, containment, and class references variables) of the
-# class with other documented classes.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-COLLABORATION_GRAPH    = YES
-
-# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GROUP_GRAPHS           = YES
-
-# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-UML_LOOK               = NO
-
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
-# class node. If there are many fields or methods and many nodes the graph may
-# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
-# number of items for each type to make the size more manageable. Set this to 0
-# for no limit. Note that the threshold may be exceeded by 50% before the limit
-# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
-# but if the number exceeds 15, the total amount of fields shown is limited to
-# 10.
-# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-UML_LIMIT_NUM_FIELDS   = 10
-
-# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
-# collaboration graphs will show the relations between templates and their
-# instances.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
-# YES then doxygen will generate a graph for each documented file showing the
-# direct and indirect include dependencies of the file with other documented
-# files.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INCLUDE_GRAPH          = YES
-
-# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
-# set to YES then doxygen will generate a graph for each documented file showing
-# the direct and indirect include dependencies of the file with other documented
-# files.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
-# dependency graph for every global function or class method.
-#
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command. Disabling a call graph can be
-# accomplished by means of the command \hidecallgraph.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CALL_GRAPH             = NO
-
-# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
-# dependency graph for every global function or class method.
-#
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command. Disabling a caller graph can be
-# accomplished by means of the command \hidecallergraph.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CALLER_GRAPH           = NO
-
-# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
-# hierarchy of all classes instead of a textual one.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
-# dependencies a directory has on other directories in a graphical way. The
-# dependency relations are determined by the #include relations between the
-# files in the directories.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DIRECTORY_GRAPH        = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. For an explanation of the image formats see the section
-# output formats in the documentation of the dot tool (Graphviz (see:
-# http://www.graphviz.org/)).
-# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
-# to make the SVG files visible in IE 9+ (other browsers do not have this
-# requirement).
-# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
-# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
-# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
-# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
-# png:gdiplus:gdiplus.
-# The default value is: png.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_IMAGE_FORMAT       = png
-
-# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
-# enable generation of interactive SVG images that allow zooming and panning.
-#
-# Note that this requires a modern browser other than Internet Explorer. Tested
-# and working are Firefox, Chrome, Safari, and Opera.
-# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
-# the SVG files visible. Older versions of IE do not have SVG support.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INTERACTIVE_SVG        = NO
-
-# The DOT_PATH tag can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_PATH               =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the \dotfile
-# command).
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOTFILE_DIRS           =
-
-# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the \mscfile
-# command).
-
-MSCFILE_DIRS           =
-
-# The DIAFILE_DIRS tag can be used to specify one or more directories that
-# contain dia files that are included in the documentation (see the \diafile
-# command).
-
-DIAFILE_DIRS           =
-
-# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-
-PLANTUML_JAR_PATH      =
-
-# When using plantuml, the specified paths are searched for files specified by
-# the !include statement in a plantuml block.
-
-PLANTUML_INCLUDE_PATH  =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
-# that will be shown in the graph. If the number of nodes in a graph becomes
-# larger than this value, doxygen will truncate the graph, which is visualized
-# by representing a node as a red box. Note that doxygen if the number of direct
-# children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
-# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-# Minimum value: 0, maximum value: 10000, default value: 50.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_GRAPH_MAX_NODES    = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
-# generated by dot. A depth value of 3 means that only nodes reachable from the
-# root by following a path via at most 3 edges will be shown. Nodes that lay
-# further from the root node will be omitted. Note that setting this option to 1
-# or 2 may greatly reduce the computation time needed for large code bases. Also
-# note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-# Minimum value: 0, maximum value: 1000, default value: 0.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-MAX_DOT_GRAPH_DEPTH    = 1000
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10) support
-# this, this feature is disabled by default.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_MULTI_TARGETS      = NO
-
-# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
-# explaining the meaning of the various boxes and arrows in the dot generated
-# graphs.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
-# files that are used to generate the various graphs.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_CLEANUP            = YES

+ 0 - 126
components/net/lwip-2.0.0/doc/doxygen/main_page.h

@@ -1,126 +0,0 @@
-/**
- * @defgroup lwip lwIP
- *
- * @defgroup infrastructure Infrastructure
- *
- * @defgroup callbackstyle_api Callback-style APIs
- * Non thread-safe APIs, callback style for maximum performance and minimum
- * memory footprint.
- * 
- * @defgroup sequential_api Sequential-style APIs
- * Sequential-style APIs, blocking functions. More overhead, but can be called
- * from any thread except TCPIP thread.
- * 
- * @defgroup addons Addons
- * 
- * @defgroup apps Applications
- */
-
-/**
- * @mainpage Overview
- * @verbinclude "README"
- */
-
-/**
- * @page upgrading Upgrading
- * @verbinclude "UPGRADING"
- */
-
-/**
- * @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 and @ref sys_prot.\n
- * You can only use @ref callbackstyle_api in this mode.\n
- * Sample code:\n
- * @include NO_SYS_SampleCode.c
- */
-
-/**
- * @defgroup lwip_os OS mode (TCPIP thread)
- * @ingroup lwip
- * Use this mode if you run an OS on your system. It is recommended to
- * use an RTOS that correctly handles priority inversion and
- * to use @ref LWIP_TCPIP_CORE_LOCKING.\n
- * Porting: implement all functions in @ref sys_layer.\n
- * You can use @ref callbackstyle_api together with @ref tcpip_callback,
- * and all @ref sequential_api.
- */
-
-/**
- * @page raw_api lwIP API
- * @verbinclude "rawapi.txt"
- */

+ 0 - 10
components/net/lwip-2.0.0/doc/doxygen/output/index.html

@@ -1,10 +0,0 @@
-<!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>

BIN
components/net/lwip-2.0.0/doc/doxygen_docs.zip


+ 0 - 113
components/net/lwip-2.0.0/doc/mdns.txt

@@ -1,113 +0,0 @@
-Multicast DNS for lwIP
-
-Author: Erik Ekman
-
-
-Note! The MDNS responder does not have all features required by the standards.
-See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal
-cases - but watch out if many devices on the same network try to use the same
-host/service instance names.
-
-
-How to enable:
-==============
-
-MDNS support does not depend on DNS.
-MDNS supports using IPv4 only, v6 only, or v4+v6.
-
-To enable MDNS responder, set
-  LWIP_MDNS_RESPONDER = 1
-in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build.
-
-The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
-default is 1.
-
-Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB.
-Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif).
-
-MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
-MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
-generated.
-
-The MDNS code puts its structs on the stack where suitable to reduce dynamic
-memory allocation. It may use up to 1kB of stack.
-
-MDNS needs a strncasecmp() implementation. If you have one, define
-LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation
-for you.
-
-
-How to use:
-===========
-
-Call mdns_resp_init() during system initialization.
-This opens UDP sockets on port 5353 for IPv4 and IPv6.
-
-
-To start responding on a netif, run
-  mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
-
-The hostname will be copied. If this returns successfully, the netif will join
-the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
-to port 5353 will be handled:
-- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
-- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
-  returns <hostname>.local
-Answers will use the supplied TTL (in seconds)
-MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
-since the default case-insensitive comparison assumes this.
-
-It is recommended to call this function after an IPv4 address has been set,
-since there is currently no check if the v4 address is valid.
-
-Call mdns_resp_netif_settings_changed() every time the IP address
-on the netif has changed.
-
-To stop responding on a netif, run
-  mdns_resp_remove_netif(struct netif *netif)
-
-
-Adding services:
-================
-
-The netif first needs to be registered. Then run
-  mdns_resp_add_service(struct netif *netif, char *name, char *service,
-      u16_t proto, u16_t port, u32_t dns_ttl,
-      service_get_txt_fn_t txt_fn, void *txt_userdata);
-
-The name and service pointers will be copied. Name refers to the name of the
-service instance, and service is the type of service, like _http
-proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
-If this call returns successfully, the following queries will be answered:
-- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
-- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
-- <name>.<service>.<proto>.local type SRV returns hostname and port of service
-- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
-  with the supplied userdata. The callback adds strings to the reply by calling
-  mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
-   int txt_len). Example callback method:
-
-   static void srv_txt(struct mdns_service *service, void *txt_userdata)
-   {
-     res = mdns_resp_add_service_txtitem(service, "path=/", 6);
-     LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
-   }
-
-  Since a hostname struct is used for TXT storage each single item can be max
-  63 bytes long, and  the total max length (including length bytes for each
-  item) is 255 bytes.
-
-If your device runs a webserver on port 80, an example call might be:
-
-  mdns_resp_add_service(netif, "myweb", "_http"
-      DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
-
-which will publish myweb._http._tcp.local for any hosts looking for web servers,
-and point them to <hostname>.local:80
-
-Relevant information will be sent as additional records to reduce number of
-requests required from a client.
-
-Removing services is currently not supported. Services are removed when the
-netif is removed.
-

+ 0 - 529
components/net/lwip-2.0.0/doc/ppp.txt

@@ -1,529 +0,0 @@
-PPP interface for lwIP
-
-Author: Sylvain Rochet
-
-Table of Contents:
-
-1 - Supported PPP protocols and features
-2 - Raw API PPP example for all protocols
-3 - PPPoS input path (raw API, IRQ safe API, TCPIP API)
-4 - Thread safe PPP API (PPPAPI)
-5 - Notify phase callback (PPP_NOTIFY_PHASE)
-6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
-
-
-
-1 Supported PPP protocols and features
-======================================
-
-Supported Low level protocols:
-* PPP over serial using HDLC-like framing, such as wired dialup modems
-  or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems
-* PPP over Ethernet, such as xDSL modems
-* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),
-  IP tunnel over UDP, such as VPN access
-
-Supported auth protocols:
-* PAP, Password Authentication Protocol
-* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5
-* MSCHAPv1, Microsoft version of CHAP, version 1
-* MSCHAPv2, Microsoft version of CHAP, version 2
-* EAP, Extensible Authentication Protocol
-
-Supported address protocols:
-* IPCP, IP Control Protocol, IPv4 addresses negotiation
-* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
-
-Supported encryption protocols:
-* MPPE, Microsoft Point-to-Point Encryption
-
-Supported compression or miscellaneous protocols, for serial links only:
-* PFC, Protocol Field Compression
-* ACFC, Address-and-Control-Field-Compression
-* ACCM, Asynchronous-Control-Character-Map
-* VJ, Van Jacobson TCP/IP Header Compression
-
-
-
-2 Raw API PPP example for all protocols
-=======================================
-
-As usual, raw API for lwIP means the lightweight API which *MUST* only be used
-for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.
-
-/*
- * Globals
- * =======
- */
-
-/* The PPP control block */
-ppp_pcb *ppp;
-
-/* The PPP IP interface */
-struct netif ppp_netif;
-
-
-/*
- * PPP status callback
- * ===================
- *
- * PPP status callback is called on PPP status change (up, down, …) from lwIP
- * core thread
- */
-
-/* PPP status callback example */
-static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
-  struct netif *pppif = ppp_netif(pcb);
-  LWIP_UNUSED_ARG(ctx);
-
-  switch(err_code) {
-    case PPPERR_NONE: {
-#if LWIP_DNS
-      const ip_addr_t *ns;
-#endif /* LWIP_DNS */
-      printf("status_cb: Connected\n");
-#if PPP_IPV4_SUPPORT
-      printf("   our_ipaddr  = %s\n", ipaddr_ntoa(&pppif->ip_addr));
-      printf("   his_ipaddr  = %s\n", ipaddr_ntoa(&pppif->gw));
-      printf("   netmask     = %s\n", ipaddr_ntoa(&pppif->netmask));
-#if LWIP_DNS
-      ns = dns_getserver(0);
-      printf("   dns1        = %s\n", ipaddr_ntoa(ns));
-      ns = dns_getserver(1);
-      printf("   dns2        = %s\n", ipaddr_ntoa(ns));
-#endif /* LWIP_DNS */
-#endif /* PPP_IPV4_SUPPORT */
-#if PPP_IPV6_SUPPORT
-      printf("   our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
-#endif /* PPP_IPV6_SUPPORT */
-      break;
-    }
-    case PPPERR_PARAM: {
-      printf("status_cb: Invalid parameter\n");
-      break;
-    }
-    case PPPERR_OPEN: {
-      printf("status_cb: Unable to open PPP session\n");
-      break;
-    }
-    case PPPERR_DEVICE: {
-      printf("status_cb: Invalid I/O device for PPP\n");
-      break;
-    }
-    case PPPERR_ALLOC: {
-      printf("status_cb: Unable to allocate resources\n");
-      break;
-    }
-    case PPPERR_USER: {
-      printf("status_cb: User interrupt\n");
-      break;
-    }
-    case PPPERR_CONNECT: {
-      printf("status_cb: Connection lost\n");
-      break;
-    }
-    case PPPERR_AUTHFAIL: {
-      printf("status_cb: Failed authentication challenge\n");
-      break;
-    }
-    case PPPERR_PROTOCOL: {
-      printf("status_cb: Failed to meet protocol\n");
-      break;
-    }
-    case PPPERR_PEERDEAD: {
-      printf("status_cb: Connection timeout\n");
-      break;
-    }
-    case PPPERR_IDLETIMEOUT: {
-      printf("status_cb: Idle Timeout\n");
-      break;
-    }
-    case PPPERR_CONNECTTIME: {
-      printf("status_cb: Max connect time reached\n");
-      break;
-    }
-    case PPPERR_LOOPBACK: {
-      printf("status_cb: Loopback detected\n");
-      break;
-    }
-    default: {
-      printf("status_cb: Unknown error code %d\n", err_code);
-      break;
-    }
-  }
-
-/*
- * This should be in the switch case, this is put outside of the switch
- * case for example readability.
- */
-
-  if (err_code == PPPERR_NONE) {
-    return;
-  }
-
-  /* ppp_close() was previously called, don't reconnect */
-  if (err_code == PPPERR_USER) {
-    /* ppp_free(); -- can be called here */
-    return;
-  }
-
-  /*
-   * Try to reconnect in 30 seconds, if you need a modem chatscript you have
-   * to do a much better signaling here ;-)
-   */
-  ppp_connect(pcb, 30);
-  /* OR ppp_listen(pcb); */
-}
-
-
-/*
- * Creating a new PPPoS session
- * ============================
- *
- * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.
- */
-
-#include "netif/ppp/pppos.h"
-
-/*
- * PPPoS serial output callback
- *
- * ppp_pcb, PPP control block
- * data, buffer to write to serial port
- * len, length of the data buffer
- * ctx, optional user-provided callback context pointer
- *
- * Return value: len if write succeed
- */
-static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
-  return uart_write(UART, data, len);
-}
-
-/*
- * Create a new PPPoS interface
- *
- * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
- * output_cb, PPPoS serial output callback
- * status_cb, PPP status callback, called on PPP status change (up, down, …)
- * ctx_cb, optional user-provided callback context pointer
- */
-ppp = pppos_create(&ppp_netif,
-       output_cb, status_cb, ctx_cb);
-
-
-/*
- * Creating a new PPPoE session
- * ============================
- */
-
-#include "netif/ppp/pppoe.h"
-
-/*
- * Create a new PPPoE interface
- *
- * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
- * ethif, already existing and setup Ethernet interface to use
- * service_name, PPPoE service name discriminator (not supported yet)
- * concentrator_name, PPPoE concentrator name discriminator (not supported yet)
- * status_cb, PPP status callback, called on PPP status change (up, down, …)
- * ctx_cb, optional user-provided callback context pointer
- */
-ppp = pppoe_create(&ppp_netif,
-       &ethif,
-       service_name, concentrator_name,
-       status_cb, ctx_cb);
-
-
-/*
- * Creating a new PPPoL2TP session
- * ===============================
- */
-
-#include "netif/ppp/pppol2tp.h"
-
-/*
- * Create a new PPPoL2TP interface
- *
- * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
- * netif, optional already existing and setup output netif, necessary if you
- *        want to set this interface as default route to settle the chicken
- *        and egg problem with VPN links
- * ipaddr, IP to connect to
- * port, UDP port to connect to (usually 1701)
- * secret, L2TP secret to use
- * secret_len, size in bytes of the L2TP secret
- * status_cb, PPP status callback, called on PPP status change (up, down, …)
- * ctx_cb, optional user-provided callback context pointer
- */
-ppp = pppol2tp_create(&ppp_netif,
-       struct netif *netif, ip_addr_t *ipaddr, u16_t port,
-       u8_t *secret, u8_t secret_len,
-       ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
-
-
-/*
- * Initiate PPP client connection
- * ==============================
- */
-
-/* Set this interface as default route */
-ppp_set_default(ppp);
-
-/*
- * Basic PPP client configuration. Can only be set if PPP session is in the
- * dead state (i.e. disconnected). We don't need to provide thread-safe
- * equivalents through PPPAPI because those helpers are only changing
- * structure members while session is inactive for lwIP core. Configuration
- * only need to be done once.
- */
-
-/* Ask the peer for up to 2 DNS server addresses. */
-ppp_set_usepeerdns(ppp, 1);
-
-/* Auth configuration, this is pretty self-explanatory */
-ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
-
-/*
- * Initiate PPP negotiation, without waiting (holdoff=0), can only be called
- * if PPP session is in the dead state (i.e. disconnected).
- */
-u16_t holdoff = 0;
-ppp_connect(ppp, holdoff);
-
-
-/*
- * Initiate PPP server listener
- * ============================
- */
-
-/*
- * Basic PPP server configuration. Can only be set if PPP session is in the
- * dead state (i.e. disconnected). We don't need to provide thread-safe
- * equivalents through PPPAPI because those helpers are only changing
- * structure members while session is inactive for lwIP core. Configuration
- * only need to be done once.
- */
-ip4_addr_t addr;
-
-/* Set our address */
-IP4_ADDR(&addr, 192,168,0,1);
-ppp_set_ipcp_ouraddr(ppp, &addr);
-
-/* Set peer(his) address */
-IP4_ADDR(&addr, 192,168,0,2);
-ppp_set_ipcp_hisaddr(ppp, &addr);
-
-/* Set primary DNS server */
-IP4_ADDR(&addr, 192,168,10,20);
-ppp_set_ipcp_dnsaddr(ppp, 0, &addr);
-
-/* Set secondary DNS server */
-IP4_ADDR(&addr, 192,168,10,21);
-ppp_set_ipcp_dnsaddr(ppp, 1, &addr);
-
-/* Auth configuration, this is pretty self-explanatory */
-ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
-
-/* Require peer to authenticate */
-ppp_set_auth_required(ppp, 1);
-
-/*
- * Only for PPPoS, the PPP session should be up and waiting for input.
- *
- * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.
- * The listen call is meant for future support of PPPoE and PPPoL2TP server
- * mode, where we will need to negotiate the incoming PPPoE session or L2TP
- * session before initiating PPP itself. We need this call because there is
- * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.
- */
-ppp_set_silent(pppos, 1);
-
-/*
- * Initiate PPP listener (i.e. wait for an incoming connection), can only
- * be called if PPP session is in the dead state (i.e. disconnected).
- */
-ppp_listen(ppp);
-
-
-/*
- * Closing PPP connection
- * ======================
- */
-
-/*
- * Initiate the end of the PPP session, without carrier lost signal
- * (nocarrier=0), meaning a clean shutdown of PPP protocols.
- * You can call this function at anytime.
- */
-u8_t nocarrier = 0;
-ppp_close(ppp, nocarrier);
-/*
- * Then you must wait your status_cb() to be called, it may takes from a few
- * seconds to several tens of seconds depending on the current PPP state.
- */
-
-/*
- * Freeing a PPP connection
- * ========================
- */
-
-/*
- * Free the PPP control block, can only be called if PPP session is in the
- * dead state (i.e. disconnected). You need to call ppp_close() before.
- */
-ppp_free(ppp);
-
-
-
-3 PPPoS input path (raw API, IRQ safe API, TCPIP API)
-=====================================================
-
-Received data on serial port should be sent to lwIP using the pppos_input()
-function or the pppos_input_tcpip() function.
-
-If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
-is not IRQ safe and then *MUST* only be called inside your main loop.
-
-Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
-safe and can be safely called from an interrupt context, using that is going
-to reduce your need of buffer if pppos_input() is called byte after byte in
-your rx serial interrupt.
-
-if NO_SYS is 0, the thread safe way outside an interrupt context is to use
-the pppos_input_tcpip() function to pass input data to the lwIP core thread
-using the TCPIP API. This is thread safe in all cases but you should avoid
-passing data byte after byte because it uses heavy locking (mailbox) and it
-allocates pbuf, better fill them !
-
-if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
-from an RX thread, however pppos_input() is not thread safe by itself. You can
-do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
-ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
-at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
-really know what you are doing, your move ;-)
-
-
-/*
- * Fonction to call for received data
- *
- * ppp, PPP control block
- * buffer, input buffer
- * buffer_len, buffer length in bytes
- */
-void pppos_input(ppp, buffer, buffer_len);
-
-or
-
-void pppos_input_tcpip(ppp, buffer, buffer_len);
-
-
-
-4 Thread safe PPP API (PPPAPI)
-==============================
-
-There is a thread safe API for all corresponding ppp_* functions, you have to
-enable LWIP_PPP_API in your lwipopts.h file, then see
-include/netif/ppp/pppapi.h, this is actually pretty obvious.
-
-
-
-5 Notify phase callback (PPP_NOTIFY_PHASE)
-==========================================
-
-Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
-you configure a callback that is called on each PPP internal state change.
-This is different from the status callback which only warns you about
-up(running) and down(dead) events.
-
-Notify phase callback can be used, for example, to set a LED pattern depending
-on the current phase of the PPP session. Here is a callback example which
-tries to mimic what we usually see on xDSL modems while they are negotiating
-the link, which should be self-explanatory:
-
-static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {
-  switch (phase) {
-
-  /* Session is down (either permanently or briefly) */
-  case PPP_PHASE_DEAD:
-    led_set(PPP_LED, LED_OFF);
-    break;
-
-  /* We are between two sessions */
-  case PPP_PHASE_HOLDOFF:
-    led_set(PPP_LED, LED_SLOW_BLINK);
-    break;
-
-  /* Session just started */
-  case PPP_PHASE_INITIALIZE:
-    led_set(PPP_LED, LED_FAST_BLINK);
-    break;
-
-  /* Session is running */
-  case PPP_PHASE_RUNNING:
-    led_set(PPP_LED, LED_ON);
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-
-6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
-===============================================
-
-PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting
-from previous lwIP version is pretty easy:
-
-* Previous PPP API used an integer to identify PPP sessions, we are now
-  using ppp_pcb* control block, therefore all functions changed from "int ppp"
-  to "ppp_pcb *ppp"
-
-* struct netif was moved outside the PPP structure, you have to provide a netif
-  for PPP interface in pppoX_create() functions
-
-* PPP session are not started automatically after you created them anymore,
-  you have to call ppp_connect(), this way you can configure the session before
-  starting it.
-
-* Previous PPP API used CamelCase, we are now using snake_case.
-
-* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,
-  PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed
-  pppoe_, common functions are now prefixed ppp_.
-
-* New PPPERR_ error codes added, check you have all of them in your status
-  callback function
-
-* Only the following include files should now be used in user application:
-  #include "netif/ppp/pppapi.h"
-  #include "netif/ppp/pppos.h"
-  #include "netif/ppp/pppoe.h"
-  #include "netif/ppp/pppol2tp.h"
-
-  Functions from ppp.h can be used, but you don't need to include this header
-  file as it is already included by above header files.
-
-* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
-  your own serial rx thread
-
-* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
-  PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
-  because you might have been fooled by that
-
-* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
-  the PPPAPI API instead.
-
-* ppp_sighup and ppp_close functions were merged using an optional argument
-  "nocarrier" on ppp_close.
-
-* DNS servers are now only remotely asked if LWIP_DNS is set and if
-  ppp_set_usepeerdns() is set to true, they are now automatically registered
-  using the dns_setserver() function so you don't need to do that in the PPP
-  callback anymore.
-
-* PPPoS does not use the SIO API anymore, as such it now requires a serial
-  output callback in place of sio_write
-
-* PPP_MAXIDLEFLAG is now in ms instead of jiffies

+ 0 - 499
components/net/lwip-2.0.0/doc/rawapi.txt

@@ -1,499 +0,0 @@
-Raw TCP/IP interface for lwIP
-
-Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
-
-lwIP provides three Application Program's Interfaces (APIs) for programs
-to use for communication with the TCP/IP code:
-* low-level "core" / "callback" or "raw" API.
-* higher-level "sequential" API.
-* BSD-style socket API.
-
-The raw API (sometimes called native API) is an event-driven API designed
-to be used without an operating system that implements zero-copy send and
-receive. This API is also used by the core stack for interaction between
-the various protocols. It is the only API available when running lwIP
-without an operating system.
-
-The sequential API provides a way for ordinary, sequential, programs
-to use the lwIP stack. It is quite similar to the BSD socket API. The
-model of execution is based on the blocking open-read-write-close
-paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
-code and the application program must reside in different execution
-contexts (threads).
-
-The socket API is a compatibility API for existing applications,
-currently it is built on top of the sequential API. It is meant to
-provide all functions needed to run socket API applications running
-on other platforms (e.g. unix / windows etc.). However, due to limitations
-in the specification of this API, there might be incompatibilities
-that require small modifications of existing programs.
-
-** Multithreading
-
-lwIP started targeting single-threaded environments. When adding multi-
-threading support, instead of making the core thread-safe, another
-approach was chosen: there is one main thread running the lwIP core
-(also known as the "tcpip_thread"). When running in a multithreaded
-environment, raw API functions MUST only be called from the core thread
-since raw API functions are not protected from concurrent access (aside
-from pbuf- and memory management functions). Application threads using
-the sequential- or socket API communicate with this main thread through
-message passing.
-
-      As such, the list of functions that may be called from
-      other threads or an ISR is very limited! Only functions
-      from these API header files are thread-safe:
-      - api.h
-      - netbuf.h
-      - netdb.h
-      - netifapi.h
-      - pppapi.h
-      - sockets.h
-      - sys.h
-
-      Additionaly, memory (de-)allocation functions may be
-      called from multiple threads (not ISR!) with NO_SYS=0
-      since they are protected by SYS_LIGHTWEIGHT_PROT and/or
-      semaphores.
-
-      Netconn or Socket API functions are thread safe against the
-      core thread but they are not reentrant at the control block
-      granularity level. That is, a UDP or TCP control block must
-      not be shared among multiple threads without proper locking.
-
-      If SYS_LIGHTWEIGHT_PROT is set to 1 and
-      LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
-      pbuf_free() may also be called from another thread or
-      an ISR (since only then, mem_free - for PBUF_RAM - may
-      be called from an ISR: otherwise, the HEAP is only
-      protected by semaphores).
-
-
-** The remainder of this document discusses the "raw" API. **
-
-The raw TCP/IP interface allows the application program to integrate
-better with the TCP/IP code. Program execution is event based by
-having callback functions being called from within the TCP/IP
-code. The TCP/IP code and the application program both run in the same
-thread. The sequential API has a much higher overhead and is not very
-well suited for small systems since it forces a multithreaded paradigm
-on the application.
-
-The raw TCP/IP interface is not only faster in terms of code execution
-time but is also less memory intensive. The drawback is that program
-development is somewhat harder and application programs written for
-the raw TCP/IP interface are more difficult to understand. Still, this
-is the preferred way of writing applications that should be small in
-code size and memory usage.
-
-All APIs can be used simultaneously by different application
-programs. In fact, the sequential API is implemented as an application
-program using the raw TCP/IP interface.
-
-Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
-The former is a way of interfacing the lwIP network stack (including
-TCP and UDP), the later refers to processing raw Ethernet or IP data
-instead of TCP connections or UDP packets.
-
-Raw API applications may never block since all packet processing
-(input and output) as well as timer processing (TCP mainly) is done
-in a single execution context.
-
---- Callbacks
-
-Program execution is driven by callbacks functions, which are then
-invoked by the lwIP core when activity related to that application
-occurs. A particular application may register to be notified via a
-callback function for events such as incoming data available, outgoing
-data sent, error notifications, poll timer expiration, connection
-closed, etc. An application can provide a callback function to perform
-processing for any or all of these events. Each callback is an ordinary
-C function that is called from within the TCP/IP code. Every callback
-function is passed the current TCP or UDP connection state as an
-argument. Also, in order to be able to keep program specific state,
-the callback functions are called with a program specified argument
-that is independent of the TCP/IP state.
-
-The function for setting the application connection state is:
-
-- void tcp_arg(struct tcp_pcb *pcb, void *arg)
-
-  Specifies the program specific state that should be passed to all
-  other callback functions. The "pcb" argument is the current TCP
-  connection control block, and the "arg" argument is the argument
-  that will be passed to the callbacks.
-
-  
---- TCP connection setup
-
-The functions used for setting up connections is similar to that of
-the sequential API and of the BSD socket API. A new TCP connection
-identifier (i.e., a protocol control block - PCB) is created with the
-tcp_new() function. This PCB can then be either set to listen for new
-incoming connections or be explicitly connected to another host.
-
-- struct tcp_pcb *tcp_new(void)
-
-  Creates a new connection identifier (PCB). If memory is not
-  available for creating the new pcb, NULL is returned.
-
-- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
-                 u16_t port)
-
-  Binds the pcb to a local IP address and port number. The IP address
-  can be specified as IP_ADDR_ANY in order to bind the connection to
-  all local IP addresses.
-
-  If another connection is bound to the same port, the function will
-  return ERR_USE, otherwise ERR_OK is returned.
-
-- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
-
-  Commands a pcb to start listening for incoming connections. When an
-  incoming connection is accepted, the function specified with the
-  tcp_accept() function will be called. The pcb will have to be bound
-  to a local port with the tcp_bind() function.
-
-  The tcp_listen() function returns a new connection identifier, and
-  the one passed as an argument to the function will be
-  deallocated. The reason for this behavior is that less memory is
-  needed for a connection that is listening, so tcp_listen() will
-  reclaim the memory needed for the original connection and allocate a
-  new smaller memory block for the listening connection.
-
-  tcp_listen() may return NULL if no memory was available for the
-  listening connection. If so, the memory associated with the pcb
-  passed as an argument to tcp_listen() will not be deallocated.
-
-- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
-
-  Same as tcp_listen, but limits the number of outstanding connections
-  in the listen queue to the value specified by the backlog argument.
-  To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
-
-- void tcp_accept(struct tcp_pcb *pcb,
-                  err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
-                                   err_t err))
-
-  Specified the callback function that should be called when a new
-  connection arrives on a listening connection.
-
-- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
-                    u16_t port, err_t (* connected)(void *arg,
-                                                    struct tcp_pcb *tpcb,
-                                                    err_t err));
-
-  Sets up the pcb to connect to the remote host and sends the
-  initial SYN segment which opens the connection. 
-
-  The tcp_connect() function returns immediately; it does not wait for
-  the connection to be properly setup. Instead, it will call the
-  function specified as the fourth argument (the "connected" argument)
-  when the connection is established. If the connection could not be
-  properly established, either because the other host refused the
-  connection or because the other host didn't answer, the "err"
-  callback function of this pcb (registered with tcp_err, see below)
-  will be called.
-
-  The tcp_connect() function can return ERR_MEM if no memory is
-  available for enqueueing the SYN segment. If the SYN indeed was
-  enqueued successfully, the tcp_connect() function returns ERR_OK.
-
-
---- Sending TCP data
-
-TCP data is sent by enqueueing the data with a call to
-tcp_write(). When the data is successfully transmitted to the remote
-host, the application will be notified with a call to a specified
-callback function.
-
-- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
-                  u8_t apiflags)
-
-  Enqueues the data pointed to by the argument dataptr. The length of
-  the data is passed as the len parameter. The apiflags can be one or more of:
-  - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
-    for the data to be copied into. If this flag is not given, no new memory
-    should be allocated and the data should only be referenced by pointer. This
-    also means that the memory behind dataptr must not change until the data is
-    ACKed by the remote host
-  - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted,
-    the PSH flag is set in the last segment created by this call to tcp_write.
-    If this flag is given, the PSH flag is not set.
-
-  The tcp_write() function will fail and return ERR_MEM if the length
-  of the data exceeds the current send buffer size or if the length of
-  the queue of outgoing segment is larger than the upper limit defined
-  in lwipopts.h. The number of bytes available in the output queue can
-  be retrieved with the tcp_sndbuf() function.
-
-  The proper way to use this function is to call the function with at
-  most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
-  the application should wait until some of the currently enqueued
-  data has been successfully received by the other host and try again.
-
-- void tcp_sent(struct tcp_pcb *pcb,
-                err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
-                u16_t len))
-
-  Specifies the callback function that should be called when data has
-  successfully been received (i.e., acknowledged) by the remote
-  host. The len argument passed to the callback function gives the
-  amount bytes that was acknowledged by the last acknowledgment.
-
-  
---- Receiving TCP data
-
-TCP data reception is callback based - an application specified
-callback function is called when new data arrives. When the
-application has taken the data, it has to call the tcp_recved()
-function to indicate that TCP can advertise increase the receive
-window.
-
-- void tcp_recv(struct tcp_pcb *pcb,
-                err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
-                               struct pbuf *p, err_t err))
-
-  Sets the callback function that will be called when new data
-  arrives. The callback function will be passed a NULL pbuf to
-  indicate that the remote host has closed the connection. If
-  there are no errors and the callback function is to return
-  ERR_OK, then it must free the pbuf. Otherwise, it must not
-  free the pbuf so that lwIP core code can store it.
-
-- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
-
-  Must be called when the application has received the data. The len
-  argument indicates the length of the received data.
-
-
---- Application polling
-
-When a connection is idle (i.e., no data is either transmitted or
-received), lwIP will repeatedly poll the application by calling a
-specified callback function. This can be used either as a watchdog
-timer for killing connections that have stayed idle for too long, or
-as a method of waiting for memory to become available. For instance,
-if a call to tcp_write() has failed because memory wasn't available,
-the application may use the polling functionality to call tcp_write()
-again when the connection has been idle for a while.
-
-- void tcp_poll(struct tcp_pcb *pcb, 
-                err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
-                u8_t interval)
-
-  Specifies the polling interval and the callback function that should
-  be called to poll the application. The interval is specified in
-  number of TCP coarse grained timer shots, which typically occurs
-  twice a second. An interval of 10 means that the application would
-  be polled every 5 seconds.
-
-
---- Closing and aborting connections
-
-- err_t tcp_close(struct tcp_pcb *pcb)
-
-  Closes the connection. The function may return ERR_MEM if no memory
-  was available for closing the connection. If so, the application
-  should wait and try again either by using the acknowledgment
-  callback or the polling functionality. If the close succeeds, the
-  function returns ERR_OK.
-
-  The pcb is deallocated by the TCP code after a call to tcp_close(). 
-
-- void tcp_abort(struct tcp_pcb *pcb)
-
-  Aborts the connection by sending a RST (reset) segment to the remote
-  host. The pcb is deallocated. This function never fails.
-
-  ATTENTION: When calling this from one of the TCP callbacks, make
-  sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
-  or you will risk accessing deallocated memory or memory leaks!
-
-
-If a connection is aborted because of an error, the application is
-alerted of this event by the err callback. Errors that might abort a
-connection are when there is a shortage of memory. The callback
-function to be called is set using the tcp_err() function.
-
-- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
-       err_t err))
-
-  The error callback function does not get the pcb passed to it as a
-  parameter since the pcb may already have been deallocated.
-
-
---- UDP interface
-
-The UDP interface is similar to that of TCP, but due to the lower
-level of complexity of UDP, the interface is significantly simpler.
-
-- struct udp_pcb *udp_new(void)
-
-  Creates a new UDP pcb which can be used for UDP communication. The
-  pcb is not active until it has either been bound to a local address
-  or connected to a remote address.
-
-- void udp_remove(struct udp_pcb *pcb)
-
-  Removes and deallocates the pcb.  
-  
-- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
-                 u16_t port)
-
-  Binds the pcb to a local address. The IP-address argument "ipaddr"
-  can be IP_ADDR_ANY to indicate that it should listen to any local IP
-  address. The function currently always return ERR_OK.
-
-- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
-                    u16_t port)
-
-  Sets the remote end of the pcb. This function does not generate any
-  network traffic, but only set the remote address of the pcb.
-
-- err_t udp_disconnect(struct udp_pcb *pcb)
-
-  Remove the remote end of the pcb. This function does not generate
-  any network traffic, but only removes the remote address of the pcb.
-
-- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
-
-  Sends the pbuf p. The pbuf is not deallocated.
-
-- void udp_recv(struct udp_pcb *pcb,
-                void (* recv)(void *arg, struct udp_pcb *upcb,
-                                         struct pbuf *p,
-                                         ip_addr_t *addr,
-                                         u16_t port),
-                              void *recv_arg)
-
-  Specifies a callback function that should be called when a UDP
-  datagram is received.
-  
-
---- System initalization
-
-A truly complete and generic sequence for initializing the lwIP stack
-cannot be given because it depends on additional initializations for
-your runtime environment (e.g. timers).
-
-We can give you some idea on how to proceed when using the raw API.
-We assume a configuration using a single Ethernet netif and the
-UDP and TCP transport layers, IPv4 and the DHCP client.
-
-Call these functions in the order of appearance:
-
-- lwip_init()
-
-  Initialize the lwIP stack and all of its subsystems.
-
-- netif_add(struct netif *netif, const ip4_addr_t *ipaddr,
-            const ip4_addr_t *netmask, const ip4_addr_t *gw,
-            void *state, netif_init_fn init, netif_input_fn input)
-
-  Adds your network interface to the netif_list. Allocate a struct
-  netif and pass a pointer to this structure as the first argument.
-  Give pointers to cleared ip_addr structures when using DHCP,
-  or fill them with sane numbers otherwise. The state pointer may be NULL.
-
-  The init function pointer must point to a initialization function for
-  your Ethernet netif interface. The following code illustrates its use.
-  
-  err_t netif_if_init(struct netif *netif)
-  {
-    u8_t i;
-    
-    for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
-      netif->hwaddr[i] = some_eth_addr[i];
-    }
-    init_my_eth_device();
-    return ERR_OK;
-  }
-  
-  For Ethernet drivers, the input function pointer must point to the lwIP
-  function ethernet_input() declared in "netif/etharp.h". Other drivers
-  must use ip_input() declared in "lwip/ip.h".
-  
-- netif_set_default(struct netif *netif)
-
-  Registers the default network interface.
-
-- netif_set_link_up(struct netif *netif)
-
-  This is the hardware link state; e.g. whether cable is plugged for wired
-  Ethernet interface. This function must be called even if you don't know
-  the current state. Having link up and link down events is optional but
-  DHCP and IPv6 discover benefit well from those events.
-
-- netif_set_up(struct netif *netif)
-
-  This is the administrative (= software) state of the netif, when the
-  netif is fully configured this function must be called.
-
-- dhcp_start(struct netif *netif)
-
-  Creates a new DHCP client for this interface on the first call.
-  
-  You can peek in the netif->dhcp struct for the actual DHCP status.
-
-- sys_check_timeouts()
-
-  When the system is running, you have to periodically call
-  sys_check_timeouts() which will handle all timers for all protocols in
-  the stack; add this to your main loop or equivalent.
-
-
---- Optimalization hints
-
-The first thing you want to optimize is the lwip_standard_checksum()
-routine from src/core/inet.c. You can override this standard
-function with the #define LWIP_CHKSUM <your_checksum_routine>.
-
-There are C examples given in inet.c or you might want to
-craft an assembly function for this. RFC1071 is a good
-introduction to this subject.
-
-Other significant improvements can be made by supplying
-assembly or inline replacements for htons() and htonl()
-if you're using a little-endian architecture.
-#define lwip_htons(x) <your_htons>
-#define lwip_htonl(x) <your_htonl>
-If you #define them to htons() and htonl(), you should
-#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
-defining hton*/ntoh* compatibility macros.
-
-Check your network interface driver if it reads at
-a higher speed than the maximum wire-speed. If the
-hardware isn't serviced frequently and fast enough
-buffer overflows are likely to occur.
-
-E.g. when using the cs8900 driver, call cs8900if_service(ethif)
-as frequently as possible. When using an RTOS let the cs8900 interrupt
-wake a high priority task that services your driver using a binary
-semaphore or event flag. Some drivers might allow additional tuning
-to match your application and network.
-
-For a production release it is recommended to set LWIP_STATS to 0.
-Note that speed performance isn't influenced much by simply setting
-high values to the memory options.
-
-For more optimization hints take a look at the lwIP wiki.
-
---- Zero-copy MACs
-
-To achieve zero-copy on transmit, the data passed to the raw API must
-remain unchanged until sent. Because the send- (or write-)functions return
-when the packets have been enqueued for sending, data must be kept stable
-after that, too.
-
-This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
-must *not* be reused by the application unless their ref-count is 1.
-
-For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
-but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
-PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
-
-Also, data passed to tcp_write without the copy-flag must not be changed!
-
-Therefore, be careful which type of PBUF you use and if you copy TCP data
-or not!

+ 0 - 120
components/net/lwip-2.0.0/doc/savannah.txt

@@ -1,120 +0,0 @@
-Daily Use Guide for using Savannah for lwIP
-
-Table of Contents:
-
-1 - Obtaining lwIP from the Git repository
-2 - Committers/developers Git access using SSH
-3 - Merging a development branch to master branch
-4 - How to release lwIP
-
-
-
-1 Obtaining lwIP from the Git repository
-----------------------------------------
-
-To perform an anonymous Git clone of the master branch (this is where
-bug fixes and incremental enhancements occur), do this:
- git clone git://git.savannah.nongnu.org/lwip.git
-
-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
-
-Or, obtain a specific (fixed) release as follows:
- git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
-
-
-2 Committers/developers Git access using SSH
---------------------------------------------
-
-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.
-To create a SSH2 key pair in UNIX-like environments, do this:
- ssh-keygen -t dsa
-
-Under Windows, a recommended SSH client is "PuTTY", freely available with good
-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
-a while so that Savannah can update its configuration (This can take minutes).
-
-Try to login using SSH:
- ssh -v your_login@git.sv.gnu.org
-
-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
-
- Interactive shell login is not possible for security reasons.
- VCS commands are allowed.
- Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
- You tried to execute:
- Sorry, you are not allowed to execute that command.
- Shared connection to git.sv.gnu.org closed.
-
-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:
- 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
-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.
-
-(If SSH asks about authenticity of the host, you can check the key
-fingerprint against https://savannah.nongnu.org/git/?group=lwip
-
-
-3 - Merging a development branch to master branch
--------------------------------------------------
-
-Merging is a straightforward process in Git. How to merge all changes in a
-development branch since our last merge from main:
-
-Checkout the master branch:
- git checkout master
-
-Merge the development branch to master:
- git merge your-development-branch
-
-Resolve any conflict.
-
-Commit the merge result.
- git commit -a
-
-Push your commits:
- git push
-
-
-4 How to release lwIP
----------------------
-
-First, tag the release using Git: (I use release number 1.4.1 throughout
-this example).
- git tag -a STABLE-1_4_1
-
-Share the tag reference by pushing it to remote:
- git push origin STABLE-1_4_1
-
-Prepare the release:
- cp -r lwip lwip-1.4.1
- 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.
- tar czvf lwip-1.4.1.tar.gz 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
-
-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.bz2
- gpg -b lwip-1.4.1.zip
-
-Upload these files using anonymous FTP:
- ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
- ncftp> mput *1.4.1.*
-
-Additionally, you may post a news item on Savannah, like this:
-
-A new 1.4.1 release is now available here:
-http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
-
-You will have to submit this via the user News interface, then approve
-this via the Administrator News interface.

+ 0 - 303
components/net/lwip-2.0.0/doc/sys_arch.txt

@@ -1,303 +0,0 @@
-sys_arch interface for lwIP
-
-Author: Adam Dunkels
-        Simon Goldschmidt
-
-The operating system emulation layer provides a common interface
-between the lwIP code and the underlying operating system kernel. The
-general idea is that porting lwIP to new architectures requires only
-small changes to a few header files and a new sys_arch
-implementation. It is also possible to do a sys_arch implementation
-that does not rely on any underlying operating system.
-
-The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full
-lwIP functionality, multiple threads support can be implemented in the
-sys_arch, but this is not required for the basic lwIP
-functionality. Timer scheduling is implemented in lwIP, but can be implemented
-by the sys_arch port (LWIP_TIMERS_CUSTOM==1).
-
-In addition to the source file providing the functionality of sys_arch,
-the OS emulation layer must provide several header files defining
-macros used throughout lwip.  The files required and the macros they
-must define are listed below the sys_arch description.
-
-Semaphores can be either counting or binary - lwIP works with both
-kinds. Mailboxes should be implemented as a queue which allows multiple messages
-to be posted (implementing as a rendez-vous point where only one message can be
-posted at a time can have a highly negative impact on performance). A message
-in a mailbox is just a pointer, nothing more. 
-
-Semaphores are represented by the type "sys_sem_t" which is typedef'd
-in the sys_arch.h file. Mailboxes are equivalently represented by the
-type "sys_mbox_t". Mutexes are represented ny the type "sys_mutex_t".
-lwIP does not place any restrictions on how these types are represented
-internally.
-
-Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that
-allows both using pointers or actual OS structures to be used. This way, memory
-required for such types can be either allocated in place (globally or on the
-stack) or on the heap (allocated internally in the "*_new()" functions).
-
-The following functions must be implemented by the sys_arch:
-
-- void sys_init(void)
-
-  Is called to initialize the sys_arch layer.
-
-- 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'
-  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
-  either 0 or 1).
-  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,
-  no real error handling is implemented.
-
-- void sys_sem_free(sys_sem_t *sem)
-
-  Deallocates a semaphore.
-
-- void sys_sem_signal(sys_sem_t *sem)
-
-  Signals a semaphore.
-
-- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
-
-  Blocks the thread while waiting for the semaphore to be
-  signaled. If the "timeout" argument is non-zero, the thread should
-  only be blocked for the specified time (measured in
-  milliseconds). If the "timeout" argument is zero, the thread should be
-  blocked until the semaphore is signalled.
-
-  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
-  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
-  (i.e., it was already signaled), the function may return zero.
-
-  Notice that lwIP implements a function with a similar name,
-  sys_sem_wait(), that uses the sys_arch_sem_wait() function.
-
-- int sys_sem_valid(sys_sem_t *sem)
-
-  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 directly using OS structures, implementing this may be more complex.
-  This may also be a define, in which case the function is not prototyped.
-
-- void sys_sem_set_invalid(sys_sem_t *sem)
-
-  Invalidate a semaphore so that sys_sem_valid() returns 0.
-  ATTENTION: This does NOT mean that the semaphore shall be deallocated:
-  sys_sem_free() is always called before calling this function!
-  This may also be a define, in which case the function is not prototyped.
-
-- void sys_mutex_new(sys_mutex_t *mutex)
-
-  Creates a new mutex. The mutex is allocated to the memory that 'mutex'
-  points to (which can be both a pointer or the actual OS structure).
-  If the mutex has been created, ERR_OK should be returned. Returning any
-  other error will provide a hint what went wrong, but except for assertions,
-  no real error handling is implemented.
-
-- void sys_mutex_free(sys_mutex_t *mutex)
-
-  Deallocates a mutex.
-
-- void sys_mutex_lock(sys_mutex_t *mutex)
-  
-  Blocks the thread until the mutex can be grabbed.
-
-- void sys_mutex_unlock(sys_mutex_t *mutex)
-
-  Releases the mutex previously locked through 'sys_mutex_lock()'.
-
-- void sys_mutex_valid(sys_mutex_t *mutex)
-
-  Returns 1 if the mutes is valid, 0 if it is not valid.
-  When using pointers, a simple way is to check the pointer for != NULL.
-  When directly using OS structures, implementing this may be more complex.
-  This may also be a define, in which case the function is not prototyped.
-
-- void sys_mutex_set_invalid(sys_mutex_t *mutex)
-
-  Invalidate a mutex so that sys_mutex_valid() returns 0.
-  ATTENTION: This does NOT mean that the mutex shall be deallocated:
-  sys_mutex_free() is always called before calling this function!
-  This may also be a define, in which case the function is not prototyped.
-
-- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
-
-  Creates an empty mailbox for maximum "size" elements. Elements stored
-  in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
-  in your lwipopts.h, or ignore this parameter in your implementation
-  and use a default size.
-  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,
-  no real error handling is implemented.
-
-- void sys_mbox_free(sys_mbox_t *mbox)
-
-  Deallocates a mailbox. If there are messages still present in the
-  mailbox when the mailbox is deallocated, it is an indication of a
-  programming error in lwIP and the developer should be notified.
-
-- void sys_mbox_post(sys_mbox_t *mbox, void *msg)
-
-  Posts the "msg" to the mailbox. This function have to block until
-  the "msg" is really posted.
-
-- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
-
-  Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
-  is full, else, ERR_OK if the "msg" is posted.
-
-- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
-
-  Blocks the thread until a message arrives in the mailbox, but does
-  not block the thread longer than "timeout" milliseconds (similar to
-  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
-  parameter that is set by the function (i.e., by doing "*msg =
-  ptr"). The "msg" parameter maybe NULL to indicate that the message
-  should be dropped.
-
-  The return values are the same as for the sys_arch_sem_wait() function:
-  Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
-  timeout.
-
-  Note that a function with a similar name, sys_mbox_fetch(), is
-  implemented by lwIP. 
-
-- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
-
-  This is similar to sys_arch_mbox_fetch, however if a message is not
-  present in the mailbox, it immediately returns with the code
-  SYS_MBOX_EMPTY. On success 0 is returned.
-
-  To allow for efficient implementations, this can be defined as a
-  function-like macro in sys_arch.h instead of a normal function. For
-  example, a naive implementation could be:
-    #define sys_arch_mbox_tryfetch(mbox,msg) \
-      sys_arch_mbox_fetch(mbox,msg,1)
-  although this would introduce unnecessary delays.
-
-- int sys_mbox_valid(sys_mbox_t *mbox)
-
-  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.
-  When directly using OS structures, implementing this may be more complex.
-  This may also be a define, in which case the function is not prototyped.
-
-- void sys_mbox_set_invalid(sys_mbox_t *mbox)
-
-  Invalidate a mailbox so that sys_mbox_valid() returns 0.
-  ATTENTION: This does NOT mean that the mailbox shall be deallocated:
-  sys_mbox_free() is always called before calling this function!
-  This may also be a define, in which case the function is not prototyped.
-
-If threads are supported by the underlying operating system and if
-such functionality is needed in lwIP, the following function will have
-to be implemented as well:
-
-- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
-
-  Starts a new thread named "name" with priority "prio" that will begin its
-  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
-  and the priority are system dependent.
-
-When lwIP is used from more than one context (e.g. from multiple threads OR from
-main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled!
-
-- sys_prot_t sys_arch_protect(void)
-
-  This optional function does a "fast" critical region protection and returns
-  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
-  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
-  other words, sys_arch_protect() could be called while already protected. In
-  that case the return value indicates that it is already protected.
-
-  sys_arch_protect() is only required if your port is supporting an operating
-  system.
-
-- void sys_arch_unprotect(sys_prot_t pval)
-
-  This optional function does a "fast" set of critical region protection to the
-  value specified by pval. See the documentation for sys_arch_protect() for
-  more information. This function is only required if your port is supporting
-  an operating system.
-
-For some configurations, you also need:
-
-- u32_t sys_now(void)
-
-  This optional function returns the current time in milliseconds (don't care
-  for wraparound, this is only used for time diffs).
-  Not implementing this function means you cannot use some modules (e.g. TCP
-  timestamps, internal timeouts for NO_SYS==1).
-
-
-Note:
-
-Be careful with using mem_malloc() in sys_arch. When malloc() refers to
-mem_malloc() you can run into a circular function call problem. In mem.c
-mem_init() tries to allcate a semaphore using mem_malloc, which of course
-can't be performed when sys_arch uses mem_malloc.
-
--------------------------------------------------------------------------------
-Additional files required for the "OS support" emulation layer:
--------------------------------------------------------------------------------
-
-cc.h       - Architecture environment, some compiler specific, some
-             environment specific (probably should move env stuff 
-             to sys_arch.h.)
-
-  Typedefs for the types used by lwip -
-    u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
-
-  Compiler hints for packing lwip's structures -
-    PACK_STRUCT_FIELD(x)
-    PACK_STRUCT_STRUCT
-    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

+ 0 - 15
components/net/lwip-2.0.0/src/FILES

@@ -1,15 +0,0 @@
-api/      - The code for the high-level wrapper API. Not needed if
-            you use the lowel-level call-back/raw API.
-
-apps/     - Higher layer applications that are specifically programmed
-            with the lwIP low-level raw API.
-
-core/     - The core of the TPC/IP stack; protocol implementations,
-            memory and buffer management, and the low-level raw API.
-
-include/  - lwIP include files.
-
-netif/    - Generic network interface device drivers are kept here.
-
-For more information on the various subdirectories, check the FILES
-file in each directory.

+ 0 - 177
components/net/lwip-2.0.0/src/Filelists.mk

@@ -1,177 +0,0 @@
-#
-# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
-# All rights reserved. 
-# 
-# Redistribution and use in source and binary forms, with or without modification, 
-# are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-#    this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-#    this list of conditions and the following disclaimer in the documentation
-#    and/or other materials provided with the distribution.
-# 3. The name of the author may not be used to endorse or promote products
-#    derived from this software without specific prior written permission. 
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
-# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
-# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
-# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
-# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-# OF SUCH DAMAGE.
-#
-# This file is part of the lwIP TCP/IP stack.
-# 
-# Author: Adam Dunkels <adam@sics.se>
-#
-
-# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
-COREFILES=$(LWIPDIR)/core/init.c \
-	$(LWIPDIR)/core/def.c \
-	$(LWIPDIR)/core/dns.c \
-	$(LWIPDIR)/core/inet_chksum.c \
-	$(LWIPDIR)/core/ip.c \
-	$(LWIPDIR)/core/mem.c \
-	$(LWIPDIR)/core/memp.c \
-	$(LWIPDIR)/core/netif.c \
-	$(LWIPDIR)/core/pbuf.c \
-	$(LWIPDIR)/core/raw.c \
-	$(LWIPDIR)/core/stats.c \
-	$(LWIPDIR)/core/sys.c \
-	$(LWIPDIR)/core/tcp.c \
-	$(LWIPDIR)/core/tcp_in.c \
-	$(LWIPDIR)/core/tcp_out.c \
-	$(LWIPDIR)/core/timeouts.c \
-	$(LWIPDIR)/core/udp.c
-
-CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
-	$(LWIPDIR)/core/ipv4/dhcp.c \
-	$(LWIPDIR)/core/ipv4/etharp.c \
-	$(LWIPDIR)/core/ipv4/icmp.c \
-	$(LWIPDIR)/core/ipv4/igmp.c \
-	$(LWIPDIR)/core/ipv4/ip4_frag.c \
-	$(LWIPDIR)/core/ipv4/ip4.c \
-	$(LWIPDIR)/core/ipv4/ip4_addr.c
-
-CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
-	$(LWIPDIR)/core/ipv6/ethip6.c \
-	$(LWIPDIR)/core/ipv6/icmp6.c \
-	$(LWIPDIR)/core/ipv6/inet6.c \
-	$(LWIPDIR)/core/ipv6/ip6.c \
-	$(LWIPDIR)/core/ipv6/ip6_addr.c \
-	$(LWIPDIR)/core/ipv6/ip6_frag.c \
-	$(LWIPDIR)/core/ipv6/mld6.c \
-	$(LWIPDIR)/core/ipv6/nd6.c
-
-# APIFILES: The files which implement the sequential and socket APIs.
-APIFILES=$(LWIPDIR)/api/api_lib.c \
-	$(LWIPDIR)/api/api_msg.c \
-	$(LWIPDIR)/api/err.c \
-	$(LWIPDIR)/api/netbuf.c \
-	$(LWIPDIR)/api/netdb.c \
-	$(LWIPDIR)/api/netifapi.c \
-	$(LWIPDIR)/api/sockets.c \
-	$(LWIPDIR)/api/tcpip.c
-
-# NETIFFILES: Files implementing various generic network interface functions
-NETIFFILES=$(LWIPDIR)/netif/ethernet.c \
-	$(LWIPDIR)/netif/slipif.c
-
-# SIXLOWPAN: 6LoWPAN
-SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \
-
-# PPPFILES: PPP
-PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \
-	$(LWIPDIR)/netif/ppp/ccp.c \
-	$(LWIPDIR)/netif/ppp/chap-md5.c \
-	$(LWIPDIR)/netif/ppp/chap_ms.c \
-	$(LWIPDIR)/netif/ppp/chap-new.c \
-	$(LWIPDIR)/netif/ppp/demand.c \
-	$(LWIPDIR)/netif/ppp/eap.c \
-	$(LWIPDIR)/netif/ppp/ecp.c \
-	$(LWIPDIR)/netif/ppp/eui64.c \
-	$(LWIPDIR)/netif/ppp/fsm.c \
-	$(LWIPDIR)/netif/ppp/ipcp.c \
-	$(LWIPDIR)/netif/ppp/ipv6cp.c \
-	$(LWIPDIR)/netif/ppp/lcp.c \
-	$(LWIPDIR)/netif/ppp/magic.c \
-	$(LWIPDIR)/netif/ppp/mppe.c \
-	$(LWIPDIR)/netif/ppp/multilink.c \
-	$(LWIPDIR)/netif/ppp/ppp.c \
-	$(LWIPDIR)/netif/ppp/pppapi.c \
-	$(LWIPDIR)/netif/ppp/pppcrypt.c \
-	$(LWIPDIR)/netif/ppp/pppoe.c \
-	$(LWIPDIR)/netif/ppp/pppol2tp.c \
-	$(LWIPDIR)/netif/ppp/pppos.c \
-	$(LWIPDIR)/netif/ppp/upap.c \
-	$(LWIPDIR)/netif/ppp/utils.c \
-	$(LWIPDIR)/netif/ppp/vj.c \
-	$(LWIPDIR)/netif/ppp/polarssl/arc4.c \
-	$(LWIPDIR)/netif/ppp/polarssl/des.c \
-	$(LWIPDIR)/netif/ppp/polarssl/md4.c \
-	$(LWIPDIR)/netif/ppp/polarssl/md5.c \
-	$(LWIPDIR)/netif/ppp/polarssl/sha1.c
-
-# LWIPNOAPPSFILES: All LWIP files without apps
-LWIPNOAPPSFILES=$(COREFILES) \
-	$(CORE4FILES) \
-	$(CORE6FILES) \
-	$(APIFILES) \
-	$(NETIFFILES) \
-	$(PPPFILES) \
-	$(SIXLOWPAN)
-
-# SNMPFILES: SNMPv2c agent
-SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \
-	$(LWIPDIR)/apps/snmp/snmp_core.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_system.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \
-	$(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \
-	$(LWIPDIR)/apps/snmp/snmp_msg.c \
-	$(LWIPDIR)/apps/snmp/snmpv3.c \
-	$(LWIPDIR)/apps/snmp/snmp_netconn.c \
-	$(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \
-	$(LWIPDIR)/apps/snmp/snmp_raw.c \
-	$(LWIPDIR)/apps/snmp/snmp_scalar.c \
-	$(LWIPDIR)/apps/snmp/snmp_table.c \
-	$(LWIPDIR)/apps/snmp/snmp_threadsync.c \
-	$(LWIPDIR)/apps/snmp/snmp_traps.c \
-	$(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \
-	$(LWIPDIR)/apps/snmp/snmpv3_dummy.c
-
-# HTTPDFILES: HTTP server
-HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \
-	$(LWIPDIR)/apps/httpd/httpd.c
-
-# LWIPERFFILES: IPERF server
-LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
-
-# SNTPFILES: SNTP client
-SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
-
-# MDNSFILES: MDNS responder
-MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
-
-# NETBIOSNSFILES: NetBIOS name server
-NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
-
-# TFTPFILES: TFTP server files
-TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
-
-# LWIPAPPFILES: All LWIP APPs
-LWIPAPPFILES=$(SNMPFILES) \
-	$(HTTPDFILES) \
-	$(LWIPERFFILES) \
-	$(SNTPFILES) \
-	$(MDNSFILES) \
-	$(NETBIOSNSFILES) \
-	$(TFTPFILES)

+ 0 - 995
components/net/lwip-2.0.0/src/api/api_lib.c

@@ -1,995 +0,0 @@
-/**
- * @file
- * Sequential API External module
- * 
- * @defgroup netconn Netconn API
- * @ingroup sequential_api
- * Thread-safe, to be called from non-TCPIP threads only.
- * TX/RX handling based on @ref netbuf (containing @ref pbuf)
- * to avoid copying data around.
- * 
- * @defgroup netconn_common Common functions
- * @ingroup netconn
- * For use with TCP and UDP
- * 
- * @defgroup netconn_tcp TCP only
- * @ingroup netconn
- * TCP only functions
- * 
- * @defgroup netconn_udp UDP only
- * @ingroup netconn
- * UDP only functions
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- */
-
-/* This is the part of the API that is linked with
-   the application */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/api.h"
-#include "lwip/memp.h"
-
-#include "lwip/ip.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/priv/api_msg.h"
-#include "lwip/priv/tcp_priv.h"
-#include "lwip/priv/tcpip_priv.h"
-
-#include <string.h>
-
-#define API_MSG_VAR_REF(name)               API_VAR_REF(name)
-#define API_MSG_VAR_DECLARE(name)           API_VAR_DECLARE(struct api_msg, name)
-#define API_MSG_VAR_ALLOC(name)             API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM)
-#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL)
-#define API_MSG_VAR_FREE(name)              API_VAR_FREE(MEMP_API_MSG, name)
-
-static err_t netconn_close_shutdown(struct netconn *conn, u8_t how);
-
-/**
- * Call the lower part of a netconn_* function
- * This function is then running in the thread context
- * of tcpip_thread and has exclusive access to lwIP core code.
- *
- * @param fn function to call
- * @param apimsg a struct containing the function to call and its parameters
- * @return ERR_OK if the function was called, another err_t if not
- */
-static err_t
-netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg)
-{
-  err_t err;
-
-#ifdef LWIP_DEBUG
-  /* catch functions that don't set err */
-  apimsg->err = ERR_VAL;
-#endif /* LWIP_DEBUG */
-
-#if LWIP_NETCONN_SEM_PER_THREAD
-  apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-  err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
-  if (err == ERR_OK) {
-    return apimsg->err;
-  }
-  return err;
-}
-
-/**
- * Create a new netconn (of a specific type) that has a callback function.
- * The corresponding pcb is also created.
- *
- * @param t the type of 'connection' to create (@see enum netconn_type)
- * @param proto the IP protocol for RAW IP pcbs
- * @param callback a function to call on status changes (RX available, TX'ed)
- * @return a newly allocated struct netconn or
- *         NULL on memory error
- */
-struct netconn*
-netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
-{
-  struct netconn *conn;
-  API_MSG_VAR_DECLARE(msg);
-  API_MSG_VAR_ALLOC_RETURN_NULL(msg);
-
-  conn = netconn_alloc(t, callback);
-  if (conn != NULL) {
-    err_t err;
-
-    API_MSG_VAR_REF(msg).msg.n.proto = proto;
-    API_MSG_VAR_REF(msg).conn = conn;
-    err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg));
-    if (err != ERR_OK) {
-      LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
-      LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
-#if LWIP_TCP
-      LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
-#endif /* LWIP_TCP */
-#if !LWIP_NETCONN_SEM_PER_THREAD
-      LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
-      sys_sem_free(&conn->op_completed);
-#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
-      sys_mbox_free(&conn->recvmbox);
-      memp_free(MEMP_NETCONN, conn);
-      API_MSG_VAR_FREE(msg);
-      return NULL;
-    }
-  }
-  API_MSG_VAR_FREE(msg);
-  return conn;
-}
-
-/**
- * @ingroup netconn_common
- * Close a netconn 'connection' and free its resources.
- * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
- * after this returns.
- *
- * @param conn the netconn to delete
- * @return ERR_OK if the connection was deleted
- */
-err_t
-netconn_delete(struct netconn *conn)
-{
-  err_t err;
-  API_MSG_VAR_DECLARE(msg);
-
-  /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
-  if (conn == NULL) {
-    return ERR_OK;
-  }
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
-  /* get the time we started, which is later compared to
-     sys_now() + conn->send_timeout */
-  API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
-#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-#if LWIP_TCP
-  API_MSG_VAR_REF(msg).msg.sd.polls_left =
-    ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
-#endif /* LWIP_TCP */
-#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-  err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  if (err != ERR_OK) {
-    return err;
-  }
-
-  netconn_free(conn);
-
-  return ERR_OK;
-}
-
-/**
- * Get the local or remote IP address and port of a netconn.
- * For RAW netconns, this returns the protocol instead of a port!
- *
- * @param conn the netconn to query
- * @param addr a pointer to which to save the IP address
- * @param port a pointer to which to save the port (or protocol for RAW)
- * @param local 1 to get the local IP address, 0 to get the remote one
- * @return ERR_CONN for invalid connections
- *         ERR_OK if the information was retrieved
- */
-err_t
-netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
-  LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
-  LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.ad.local = local;
-#if LWIP_MPU_COMPATIBLE
-  err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg));
-  *addr = msg->msg.ad.ipaddr;
-  *port = msg->msg.ad.port;
-#else /* LWIP_MPU_COMPATIBLE */
-  msg.msg.ad.ipaddr = addr;
-  msg.msg.ad.port = port;
-  err = netconn_apimsg(lwip_netconn_do_getaddr, &msg);
-#endif /* LWIP_MPU_COMPATIBLE */
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_common
- * Bind a netconn to a specific local IP address and port.
- * Binding one netconn twice might not always be checked correctly!
- *
- * @param conn the netconn to bind
- * @param addr the local IP address to bind the netconn to 
- *             (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses)
- * @param port the local port to bind the netconn to (not used for RAW)
- * @return ERR_OK if bound, any other err_t on failure
- */
-err_t
-netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-  
-  LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
-
-  /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
-  if (addr == NULL) {
-    addr = IP4_ADDR_ANY;
-  }
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
-  API_MSG_VAR_REF(msg).msg.bc.port = port;
-  err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_common
- * Connect a netconn to a specific remote IP address and port.
- *
- * @param conn the netconn to connect
- * @param addr the remote IP address to connect to
- * @param port the remote port to connect to (no used for RAW)
- * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
- */
-err_t
-netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
-
-  /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
-  if (addr == NULL) {
-    addr = IP4_ADDR_ANY;
-  }
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
-  API_MSG_VAR_REF(msg).msg.bc.port = port;
-  err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_udp
- * Disconnect a netconn from its current peer (only valid for UDP netconns).
- *
- * @param conn the netconn to disconnect
- * @return See @ref err_t
- */
-err_t
-netconn_disconnect(struct netconn *conn)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-  err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_tcp
- * Set a TCP netconn into listen mode
- *
- * @param conn the tcp netconn to set to listen mode
- * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
- * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
- *         don't return any error (yet?))
- */
-err_t
-netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
-{
-#if LWIP_TCP
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
-  LWIP_UNUSED_ARG(backlog);
-
-  LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-#if TCP_LISTEN_BACKLOG
-  API_MSG_VAR_REF(msg).msg.lb.backlog = backlog;
-#endif /* TCP_LISTEN_BACKLOG */
-  err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-#else /* LWIP_TCP */
-  LWIP_UNUSED_ARG(conn);
-  LWIP_UNUSED_ARG(backlog);
-  return ERR_ARG;
-#endif /* LWIP_TCP */
-}
-
-/**
- * @ingroup netconn_tcp
- * Accept a new connection on a TCP listening netconn.
- *
- * @param conn the TCP listen netconn
- * @param new_conn pointer where the new connection is stored
- * @return ERR_OK if a new connection has been received or an error
- *                code otherwise
- */
-err_t
-netconn_accept(struct netconn *conn, struct netconn **new_conn)
-{
-#if LWIP_TCP
-  void *accept_ptr;
-  struct netconn *newconn;
-  err_t err;
-#if TCP_LISTEN_BACKLOG
-  API_MSG_VAR_DECLARE(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-
-  LWIP_ERROR("netconn_accept: invalid pointer",    (new_conn != NULL),                  return ERR_ARG;);
-  *new_conn = NULL;
-  LWIP_ERROR("netconn_accept: invalid conn",       (conn != NULL),                      return ERR_ARG;);
-
-  err = conn->last_err;
-  if (ERR_IS_FATAL(err)) {
-    /* don't recv on fatal errors: this might block the application task
-       waiting on acceptmbox forever! */
-    return err;
-  }
-  if (!sys_mbox_valid(&conn->acceptmbox)) {
-    return ERR_CLSD;
-  }
-
-#if TCP_LISTEN_BACKLOG
-  API_MSG_VAR_ALLOC(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-
-#if LWIP_SO_RCVTIMEO
-  if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
-#if TCP_LISTEN_BACKLOG
-    API_MSG_VAR_FREE(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-    return ERR_TIMEOUT;
-  }
-#else
-  sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
-  newconn = (struct netconn *)accept_ptr;
-  /* Register event with callback */
-  API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
-
-  if (accept_ptr == &netconn_aborted) {
-    /* a connection has been aborted: out of pcbs or out of netconns during accept */
-    /* @todo: set netconn error, but this would be fatal and thus block further accepts */
-#if TCP_LISTEN_BACKLOG
-    API_MSG_VAR_FREE(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-    return ERR_ABRT;
-  }
-  if (newconn == NULL) {
-    /* connection has been aborted */
-    /* in this special case, we set the netconn error from application thread, as
-       on a ready-to-accept listening netconn, there should not be anything running
-       in tcpip_thread */
-    NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
-#if TCP_LISTEN_BACKLOG
-    API_MSG_VAR_FREE(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-    return ERR_CLSD;
-  }
-#if TCP_LISTEN_BACKLOG
-  /* Let the stack know that we have accepted the connection. */
-  API_MSG_VAR_REF(msg).conn = newconn;
-  /* don't care for the return value of lwip_netconn_do_recv */
-  netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-#endif /* TCP_LISTEN_BACKLOG */
-
-  *new_conn = newconn;
-  /* don't set conn->last_err: it's only ERR_OK, anyway */
-  return ERR_OK;
-#else /* LWIP_TCP */
-  LWIP_UNUSED_ARG(conn);
-  LWIP_UNUSED_ARG(new_conn);
-  return ERR_ARG;
-#endif /* LWIP_TCP */
-}
-
-/**
- * @ingroup netconn_common
- * Receive data: actual implementation that doesn't care whether pbuf or netbuf
- * is received
- *
- * @param conn the netconn from which to receive data
- * @param new_buf pointer where a new pbuf/netbuf is stored when received data
- * @return ERR_OK if data has been received, an error code otherwise (timeout,
- *                memory error or another error)
- */
-static err_t
-netconn_recv_data(struct netconn *conn, void **new_buf)
-{
-  void *buf = NULL;
-  u16_t len;
-  err_t err;
-#if LWIP_TCP
-  API_MSG_VAR_DECLARE(msg);
-#if LWIP_MPU_COMPATIBLE
-  msg = NULL;
-#endif
-#endif /* LWIP_TCP */
-
-  LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
-  *new_buf = NULL;
-  LWIP_ERROR("netconn_recv: invalid conn",    (conn != NULL),    return ERR_ARG;);
-#if LWIP_TCP
-#if (LWIP_UDP || LWIP_RAW)
-  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  {
-    if (!sys_mbox_valid(&conn->recvmbox)) {
-      /* This happens when calling this function after receiving FIN */
-      return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD;
-    }
-  }
-#endif /* LWIP_TCP */
-  LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
-
-  err = conn->last_err;
-  if (ERR_IS_FATAL(err)) {
-    /* don't recv on fatal errors: this might block the application task
-       waiting on recvmbox forever! */
-    /* @todo: this does not allow us to fetch data that has been put into recvmbox
-       before the fatal error occurred - is that a problem? */
-    return err;
-  }
-#if LWIP_TCP
-#if (LWIP_UDP || LWIP_RAW)
-  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  {
-    API_MSG_VAR_ALLOC(msg);
-  }
-#endif /* LWIP_TCP */
-
-#if LWIP_SO_RCVTIMEO
-  if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
-#if LWIP_TCP
-#if (LWIP_UDP || LWIP_RAW)
-    if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
-#endif /* (LWIP_UDP || LWIP_RAW) */
-    {
-      API_MSG_VAR_FREE(msg);
-    }
-#endif /* LWIP_TCP */
-    return ERR_TIMEOUT;
-  }
-#else
-  sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
-
-#if LWIP_TCP
-#if (LWIP_UDP || LWIP_RAW)
-  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  {
-    /* Let the stack know that we have taken the data. */
-    /* @todo: Speedup: Don't block and wait for the answer here
-       (to prevent multiple thread-switches). */
-    API_MSG_VAR_REF(msg).conn = conn;
-    if (buf != NULL) {
-      API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len;
-    } else {
-      API_MSG_VAR_REF(msg).msg.r.len = 1;
-    }
-
-    /* don't care for the return value of lwip_netconn_do_recv */
-    netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg));
-    API_MSG_VAR_FREE(msg);
-
-    /* If we are closed, we indicate that we no longer wish to use the socket */
-    if (buf == NULL) {
-      API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
-      if (conn->pcb.ip == NULL) {
-        /* race condition: RST during recv */
-        return conn->last_err == ERR_OK ? ERR_RST : conn->last_err;
-      }
-      /* RX side is closed, so deallocate the recvmbox */
-      netconn_close_shutdown(conn, NETCONN_SHUT_RD);
-      /* Don' store ERR_CLSD as conn->err since we are only half-closed */
-      return ERR_CLSD;
-    }
-    len = ((struct pbuf *)buf)->tot_len;
-  }
-#endif /* LWIP_TCP */
-#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
-  else
-#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
-#if (LWIP_UDP || LWIP_RAW)
-  {
-    LWIP_ASSERT("buf != NULL", buf != NULL);
-    len = netbuf_len((struct netbuf *)buf);
-  }
-#endif /* (LWIP_UDP || LWIP_RAW) */
-
-#if LWIP_SO_RCVBUF
-  SYS_ARCH_DEC(conn->recv_avail, len);
-#endif /* LWIP_SO_RCVBUF */
-  /* Register event with callback */
-  API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
-
-  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
-
-  *new_buf = buf;
-  /* don't set conn->last_err: it's only ERR_OK, anyway */
-  return ERR_OK;
-}
-
-/**
- * @ingroup netconn_tcp
- * Receive data (in form of a pbuf) from a TCP netconn
- *
- * @param conn the netconn from which to receive data
- * @param new_buf pointer where a new pbuf is stored when received data
- * @return ERR_OK if data has been received, an error code otherwise (timeout,
- *                memory error or another error)
- *         ERR_ARG if conn is not a TCP netconn
- */
-err_t
-netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
-{
-  LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
-             NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
-
-  return netconn_recv_data(conn, (void **)new_buf);
-}
-
-/**
- * @ingroup netconn_common
- * Receive data (in form of a netbuf containing a packet buffer) from a netconn
- *
- * @param conn the netconn from which to receive data
- * @param new_buf pointer where a new netbuf is stored when received data
- * @return ERR_OK if data has been received, an error code otherwise (timeout,
- *                memory error or another error)
- */
-err_t
-netconn_recv(struct netconn *conn, struct netbuf **new_buf)
-{
-#if LWIP_TCP
-  struct netbuf *buf = NULL;
-  err_t err;
-#endif /* LWIP_TCP */
-
-  LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
-  *new_buf = NULL;
-  LWIP_ERROR("netconn_recv: invalid conn",    (conn != NULL),    return ERR_ARG;);
-
-#if LWIP_TCP
-#if (LWIP_UDP || LWIP_RAW)
-  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  {
-    struct pbuf *p = NULL;
-    /* This is not a listening netconn, since recvmbox is set */
-
-    buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
-    if (buf == NULL) {
-      return ERR_MEM;
-    }
-
-    err = netconn_recv_data(conn, (void **)&p);
-    if (err != ERR_OK) {
-      memp_free(MEMP_NETBUF, buf);
-      return err;
-    }
-    LWIP_ASSERT("p != NULL", p != NULL);
-
-    buf->p = p;
-    buf->ptr = p;
-    buf->port = 0;
-    ip_addr_set_zero(&buf->addr);
-    *new_buf = buf;
-    /* don't set conn->last_err: it's only ERR_OK, anyway */
-    return ERR_OK;
-  }
-#endif /* LWIP_TCP */
-#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
-  else
-#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
-  {
-#if (LWIP_UDP || LWIP_RAW)
-    return netconn_recv_data(conn, (void **)new_buf);
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  }
-}
-
-/**
- * @ingroup netconn_udp
- * Send data (in form of a netbuf) to a specific remote IP address and port.
- * Only to be used for UDP and RAW netconns (not TCP).
- *
- * @param conn the netconn over which to send data
- * @param buf a netbuf containing the data to send
- * @param addr the remote IP address to which to send the data
- * @param port the remote port to which to send the data
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port)
-{
-  if (buf != NULL) {
-    ip_addr_set(&buf->addr, addr);
-    buf->port = port;
-    return netconn_send(conn, buf);
-  }
-  return ERR_VAL;
-}
-
-/**
- * @ingroup netconn_udp
- * Send data over a UDP or RAW netconn (that is already connected).
- *
- * @param conn the UDP or RAW netconn over which to send data
- * @param buf a netbuf containing the data to send
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_send(struct netconn *conn, struct netbuf *buf)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  LWIP_ERROR("netconn_send: invalid conn",  (conn != NULL), return ERR_ARG;);
-
-  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.b = buf;
-  err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_tcp
- * Send data over a TCP netconn.
- *
- * @param conn the TCP netconn over which to send data
- * @param dataptr pointer to the application buffer that contains the data to send
- * @param size size of the application data to send
- * @param apiflags combination of following flags :
- * - NETCONN_COPY: data will be copied into memory belonging to the stack
- * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
- * - NETCONN_DONTBLOCK: only write the data if all data can be written at once
- * @param bytes_written pointer to a location that receives the number of written bytes
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
-                     u8_t apiflags, size_t *bytes_written)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-  u8_t dontblock;
-
-  LWIP_ERROR("netconn_write: invalid conn",  (conn != NULL), return ERR_ARG;);
-  LWIP_ERROR("netconn_write: invalid conn->type",  (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
-  if (size == 0) {
-    return ERR_OK;
-  }
-  dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
-  if (dontblock && !bytes_written) {
-    /* This implies netconn_write() cannot be used for non-blocking send, since
-       it has no way to return the number of bytes written. */
-    return ERR_VAL;
-  }
-
-  API_MSG_VAR_ALLOC(msg);
-  /* non-blocking write sends as much  */
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr;
-  API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags;
-  API_MSG_VAR_REF(msg).msg.w.len = size;
-#if LWIP_SO_SNDTIMEO
-  if (conn->send_timeout != 0) {
-    /* get the time we started, which is later compared to
-        sys_now() + conn->send_timeout */
-    API_MSG_VAR_REF(msg).msg.w.time_started = sys_now();
-  } else {
-    API_MSG_VAR_REF(msg).msg.w.time_started = 0;
-  }
-#endif /* LWIP_SO_SNDTIMEO */
-
-  /* For locking the core: this _can_ be delayed on low memory/low send buffer,
-     but if it is, this is done inside api_msg.c:do_write(), so we can use the
-     non-blocking version here. */
-  err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
-  if ((err == ERR_OK) && (bytes_written != NULL)) {
-    if (dontblock
-#if LWIP_SO_SNDTIMEO
-        || (conn->send_timeout != 0)
-#endif /* LWIP_SO_SNDTIMEO */
-       ) {
-      /* nonblocking write: maybe the data has been sent partly */
-      *bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
-    } else {
-      /* blocking call succeeded: all data has been sent if it */
-      *bytes_written = size;
-    }
-  }
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_tcp
- * Close or shutdown a TCP netconn (doesn't delete it).
- *
- * @param conn the TCP netconn to close or shutdown
- * @param how fully close or only shutdown one side?
- * @return ERR_OK if the netconn was closed, any other err_t on error
- */
-static err_t
-netconn_close_shutdown(struct netconn *conn, u8_t how)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-  LWIP_UNUSED_ARG(how);
-
-  LWIP_ERROR("netconn_close: invalid conn",  (conn != NULL), return ERR_ARG;);
-
-  API_MSG_VAR_ALLOC(msg);
-  API_MSG_VAR_REF(msg).conn = conn;
-#if LWIP_TCP
-  /* shutting down both ends is the same as closing */
-  API_MSG_VAR_REF(msg).msg.sd.shut = how;
-#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
-  /* get the time we started, which is later compared to
-     sys_now() + conn->send_timeout */
-  API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
-#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-  API_MSG_VAR_REF(msg).msg.sd.polls_left =
-    ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
-#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-#endif /* LWIP_TCP */
-  err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-
-/**
- * @ingroup netconn_tcp
- * Close a TCP netconn (doesn't delete it).
- *
- * @param conn the TCP netconn to close
- * @return ERR_OK if the netconn was closed, any other err_t on error
- */
-err_t
-netconn_close(struct netconn *conn)
-{
-  /* shutting down both ends is the same as closing */
-  return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
-}
-
-/**
- * @ingroup netconn_tcp
- * Shut down one or both sides of a TCP netconn (doesn't delete it).
- *
- * @param conn the TCP netconn to shut down
- * @param shut_rx shut down the RX side (no more read possible after this)
- * @param shut_tx shut down the TX side (no more write possible after this)
- * @return ERR_OK if the netconn was closed, any other err_t on error
- */
-err_t
-netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
-{
-  return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
-}
-
-#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
-/**
- * @ingroup netconn_udp
- * Join multicast groups for UDP netconns.
- *
- * @param conn the UDP netconn for which to change multicast addresses
- * @param multiaddr IP address of the multicast group to join or leave
- * @param netif_addr the IP address of the network interface on which to send
- *                  the igmp message
- * @param join_or_leave flag whether to send a join- or leave-message
- * @return ERR_OK if the action was taken, any err_t on error
- */
-err_t
-netconn_join_leave_group(struct netconn *conn,
-                         const ip_addr_t *multiaddr,
-                         const ip_addr_t *netif_addr,
-                         enum netconn_igmp join_or_leave)
-{
-  API_MSG_VAR_DECLARE(msg);
-  err_t err;
-
-  LWIP_ERROR("netconn_join_leave_group: invalid conn",  (conn != NULL), return ERR_ARG;);
-
-  API_MSG_VAR_ALLOC(msg);
-
-  /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
-  if (multiaddr == NULL) {
-    multiaddr = IP4_ADDR_ANY;
-  }
-  if (netif_addr == NULL) {
-    netif_addr = IP4_ADDR_ANY;
-  }
-
-  API_MSG_VAR_REF(msg).conn = conn;
-  API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
-  API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr);
-  API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave;
-  err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg));
-  API_MSG_VAR_FREE(msg);
-
-  return err;
-}
-#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
-
-#if LWIP_DNS
-/**
- * @ingroup netconn_common
- * Execute a DNS query, only one IP address is returned
- *
- * @param name a string representation of the DNS host name to query
- * @param addr a preallocated ip_addr_t where to store the resolved IP address
- * @param dns_addrtype IP address type (IPv4 / IPv6)
- * @return ERR_OK: resolving succeeded
- *         ERR_MEM: memory error, try again later
- *         ERR_ARG: dns client not initialized or invalid hostname
- *         ERR_VAL: dns server response was invalid
- */
-#if LWIP_IPV4 && LWIP_IPV6
-err_t
-netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
-#else
-err_t
-netconn_gethostbyname(const char *name, ip_addr_t *addr)
-#endif
-{
-  API_VAR_DECLARE(struct dns_api_msg, msg);
-#if !LWIP_MPU_COMPATIBLE
-  sys_sem_t sem;
-#endif /* LWIP_MPU_COMPATIBLE */
-  err_t err;
-
-  LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
-  LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
-#if LWIP_MPU_COMPATIBLE
-  if (strlen(name) >= DNS_MAX_NAME_LENGTH) {
-    return ERR_ARG;
-  }
-#endif
-
-  API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM);
-#if LWIP_MPU_COMPATIBLE
-  strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1);
-  API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0;
-#else /* LWIP_MPU_COMPATIBLE */
-  msg.err = &err;
-  msg.sem = &sem;
-  API_VAR_REF(msg).addr = API_VAR_REF(addr);
-  API_VAR_REF(msg).name = name;
-#endif /* LWIP_MPU_COMPATIBLE */
-#if LWIP_IPV4 && LWIP_IPV6
-  API_VAR_REF(msg).dns_addrtype = dns_addrtype;
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-#if LWIP_NETCONN_SEM_PER_THREAD
-  API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET();
-#else /* LWIP_NETCONN_SEM_PER_THREAD*/
-  err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0);
-  if (err != ERR_OK) {
-    API_VAR_FREE(MEMP_DNS_API_MSG, msg);
-    return err;
-  }
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-  err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
-  if (err != ERR_OK) {
-#if !LWIP_NETCONN_SEM_PER_THREAD
-    sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
-#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
-    API_VAR_FREE(MEMP_DNS_API_MSG, msg);
-    return err;
-  }
-  sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
-#if !LWIP_NETCONN_SEM_PER_THREAD
-  sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
-#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
-
-#if LWIP_MPU_COMPATIBLE
-  *addr = msg->addr;
-  err = msg->err;
-#endif /* LWIP_MPU_COMPATIBLE */
-
-  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
-  return err;
-}
-#endif /* LWIP_DNS*/
-
-#if LWIP_NETCONN_SEM_PER_THREAD
-void
-netconn_thread_init(void)
-{
-  sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
-  if ((sem == NULL) || !sys_sem_valid(sem)) {
-    /* call alloc only once */
-    LWIP_NETCONN_THREAD_SEM_ALLOC();
-    LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
-  }
-}
-
-void
-netconn_thread_cleanup(void)
-{
-  sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
-  if ((sem != NULL) && sys_sem_valid(sem)) {
-    /* call free only once */
-    LWIP_NETCONN_THREAD_SEM_FREE();
-  }
-}
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-#endif /* LWIP_NETCONN */

+ 0 - 1943
components/net/lwip-2.0.0/src/api/api_msg.c

@@ -1,1943 +0,0 @@
-/**
- * @file
- * Sequential API Internal module
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/priv/api_msg.h"
-
-#include "lwip/ip.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
-#include "lwip/raw.h"
-
-#include "lwip/memp.h"
-#include "lwip/igmp.h"
-#include "lwip/dns.h"
-#include "lwip/mld6.h"
-#include "lwip/priv/tcpip_priv.h"
-
-#include <string.h>
-
-/* netconns are polled once per second (e.g. continue write on memory error) */
-#define NETCONN_TCP_POLL_INTERVAL 2
-
-#define SET_NONBLOCKING_CONNECT(conn, val)  do { if (val) { \
-  (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
-} else { \
-  (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0)
-#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
-
-/* forward declarations */
-#if LWIP_TCP
-#if LWIP_TCPIP_CORE_LOCKING
-#define WRITE_DELAYED         , 1
-#define WRITE_DELAYED_PARAM   , u8_t delayed
-#else /* LWIP_TCPIP_CORE_LOCKING */
-#define WRITE_DELAYED
-#define WRITE_DELAYED_PARAM
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-static err_t lwip_netconn_do_writemore(struct netconn *conn  WRITE_DELAYED_PARAM);
-static err_t lwip_netconn_do_close_internal(struct netconn *conn  WRITE_DELAYED_PARAM);
-#endif
-
-#if LWIP_TCPIP_CORE_LOCKING
-#define TCPIP_APIMSG_ACK(m)   NETCONN_SET_SAFE_ERR((m)->conn, (m)->err)
-#else /* LWIP_TCPIP_CORE_LOCKING */
-#define TCPIP_APIMSG_ACK(m)   do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0)
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
-#if LWIP_TCP
-u8_t netconn_aborted;
-#endif /* LWIP_TCP */
-
-#if LWIP_RAW
-/**
- * Receive callback function for RAW netconns.
- * Doesn't 'eat' the packet, only copies it and sends it to
- * conn->recvmbox
- *
- * @see raw.h (struct raw_pcb.recv) for parameters and return value
- */
-static u8_t
-recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
-    const ip_addr_t *addr)
-{
-  struct pbuf *q;
-  struct netbuf *buf;
-  struct netconn *conn;
-
-  LWIP_UNUSED_ARG(addr);
-  conn = (struct netconn *)arg;
-
-  if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) {
-#if LWIP_SO_RCVBUF
-    int recv_avail;
-    SYS_ARCH_GET(conn->recv_avail, recv_avail);
-    if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) {
-      return 0;
-    }
-#endif /* LWIP_SO_RCVBUF */
-    /* copy the whole packet into new pbufs */
-    q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
-    if (q != NULL) {
-      if (pbuf_copy(q, p) != ERR_OK) {
-        pbuf_free(q);
-        q = NULL;
-      }
-    }
-
-    if (q != NULL) {
-      u16_t len;
-      buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
-      if (buf == NULL) {
-        pbuf_free(q);
-        return 0;
-      }
-
-      buf->p = q;
-      buf->ptr = q;
-      ip_addr_copy(buf->addr, *ip_current_src_addr());
-      buf->port = pcb->protocol;
-
-      len = q->tot_len;
-      if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
-        netbuf_delete(buf);
-        return 0;
-      } else {
-#if LWIP_SO_RCVBUF
-        SYS_ARCH_INC(conn->recv_avail, len);
-#endif /* LWIP_SO_RCVBUF */
-        /* Register event with callback */
-        API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
-      }
-    }
-  }
-
-  return 0; /* do not eat the packet */
-}
-#endif /* LWIP_RAW*/
-
-#if LWIP_UDP
-/**
- * Receive callback function for UDP netconns.
- * Posts the packet to conn->recvmbox or deletes it on memory error.
- *
- * @see udp.h (struct udp_pcb.recv) for parameters
- */
-static void
-recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
-   const ip_addr_t *addr, u16_t port)
-{
-  struct netbuf *buf;
-  struct netconn *conn;
-  u16_t len;
-#if LWIP_SO_RCVBUF
-  int recv_avail;
-#endif /* LWIP_SO_RCVBUF */
-
-  LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
-  LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
-  LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
-  conn = (struct netconn *)arg;
-  LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
-
-#if LWIP_SO_RCVBUF
-  SYS_ARCH_GET(conn->recv_avail, recv_avail);
-  if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
-      ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
-#else  /* LWIP_SO_RCVBUF */
-  if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
-#endif /* LWIP_SO_RCVBUF */
-    pbuf_free(p);
-    return;
-  }
-
-  buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
-  if (buf == NULL) {
-    pbuf_free(p);
-    return;
-  } else {
-    buf->p = p;
-    buf->ptr = p;
-    ip_addr_set(&buf->addr, addr);
-    buf->port = port;
-#if LWIP_NETBUF_RECVINFO
-    {
-      /* get the UDP header - always in the first pbuf, ensured by udp_input */
-      const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr();
-#if LWIP_CHECKSUM_ON_COPY
-      buf->flags = NETBUF_FLAG_DESTADDR;
-#endif /* LWIP_CHECKSUM_ON_COPY */
-      ip_addr_set(&buf->toaddr, ip_current_dest_addr());
-      buf->toport_chksum = udphdr->dest;
-    }
-#endif /* LWIP_NETBUF_RECVINFO */
-  }
-
-  len = p->tot_len;
-  if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
-    netbuf_delete(buf);
-    return;
-  } else {
-#if LWIP_SO_RCVBUF
-    SYS_ARCH_INC(conn->recv_avail, len);
-#endif /* LWIP_SO_RCVBUF */
-    /* Register event with callback */
-    API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
-  }
-}
-#endif /* LWIP_UDP */
-
-#if LWIP_TCP
-/**
- * Receive callback function for TCP netconns.
- * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
- *
- * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
- */
-static err_t
-recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
-{
-  struct netconn *conn;
-  u16_t len;
-
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
-  LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
-  conn = (struct netconn *)arg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-  LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
-
-  if (!sys_mbox_valid(&conn->recvmbox)) {
-    /* recvmbox already deleted */
-    if (p != NULL) {
-      tcp_recved(pcb, p->tot_len);
-      pbuf_free(p);
-    }
-    return ERR_OK;
-  }
-  /* Unlike for UDP or RAW pcbs, don't check for available space
-     using recv_avail since that could break the connection
-     (data is already ACKed) */
-
-  /* don't overwrite fatal errors! */
-  if (err != ERR_OK) {
-    NETCONN_SET_SAFE_ERR(conn, err);
-  }
-
-  if (p != NULL) {
-    len = p->tot_len;
-  } else {
-    len = 0;
-  }
-
-  if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
-    /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
-    return ERR_MEM;
-  } else {
-#if LWIP_SO_RCVBUF
-    SYS_ARCH_INC(conn->recv_avail, len);
-#endif /* LWIP_SO_RCVBUF */
-    /* Register event with callback */
-    API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Poll callback function for TCP netconns.
- * Wakes up an application thread that waits for a connection to close
- * or data to be sent. The application thread then takes the
- * appropriate action to go on.
- *
- * Signals the conn->sem.
- * netconn_close waits for conn->sem if closing failed.
- *
- * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
- */
-static err_t
-poll_tcp(void *arg, struct tcp_pcb *pcb)
-{
-  struct netconn *conn = (struct netconn *)arg;
-
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_ASSERT("conn != NULL", (conn != NULL));
-
-  if (conn->state == NETCONN_WRITE) {
-    lwip_netconn_do_writemore(conn  WRITE_DELAYED);
-  } else if (conn->state == NETCONN_CLOSE) {
-#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER
-    if (conn->current_msg && conn->current_msg->msg.sd.polls_left) {
-      conn->current_msg->msg.sd.polls_left--;
-    }
-#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */
-    lwip_netconn_do_close_internal(conn  WRITE_DELAYED);
-  }
-  /* @todo: implement connect timeout here? */
-
-  /* Did a nonblocking write fail before? Then check available write-space. */
-  if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
-    /* If the queued byte- or pbuf-count drops below the configured low-water limit,
-       let select mark this pcb as writable again. */
-    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
-      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
-      conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
-      API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
-    }
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Sent callback function for TCP netconns.
- * Signals the conn->sem and calls API_EVENT.
- * netconn_write waits for conn->sem if send buffer is low.
- *
- * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
- */
-static err_t
-sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
-{
-  struct netconn *conn = (struct netconn *)arg;
-
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_ASSERT("conn != NULL", (conn != NULL));
-
-  if (conn) {
-    if (conn->state == NETCONN_WRITE) {
-      lwip_netconn_do_writemore(conn  WRITE_DELAYED);
-    } else if (conn->state == NETCONN_CLOSE) {
-      lwip_netconn_do_close_internal(conn  WRITE_DELAYED);
-    }
-
-    /* If the queued byte- or pbuf-count drops below the configured low-water limit,
-       let select mark this pcb as writable again. */
-    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
-      (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
-      conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
-      API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
-    }
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Error callback function for TCP netconns.
- * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
- * The application thread has then to decide what to do.
- *
- * @see tcp.h (struct tcp_pcb.err) for parameters
- */
-static void
-err_tcp(void *arg, err_t err)
-{
-  struct netconn *conn;
-  enum netconn_state old_state;
-
-  conn = (struct netconn *)arg;
-  LWIP_ASSERT("conn != NULL", (conn != NULL));
-
-  conn->pcb.tcp = NULL;
-
-  /* reset conn->state now before waking up other threads */
-  old_state = conn->state;
-  conn->state = NETCONN_NONE;
-
-  if (old_state == NETCONN_CLOSE) {
-    /* RST during close: let close return success & dealloc the netconn */
-    err = ERR_OK;
-    NETCONN_SET_SAFE_ERR(conn, ERR_OK);
-  } else {
-    /* no check since this is always fatal! */
-    SYS_ARCH_SET(conn->last_err, err);
-  }
-
-  /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */
-
-  /* Notify the user layer about a connection error. Used to signal select. */
-  API_EVENT(conn, NETCONN_EVT_ERROR, 0);
-  /* Try to release selects pending on 'read' or 'write', too.
-     They will get an error if they actually try to read or write. */
-  API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
-  API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
-
-  /* pass NULL-message to recvmbox to wake up pending recv */
-  if (sys_mbox_valid(&conn->recvmbox)) {
-    /* use trypost to prevent deadlock */
-    sys_mbox_trypost(&conn->recvmbox, NULL);
-  }
-  /* pass NULL-message to acceptmbox to wake up pending accept */
-  if (sys_mbox_valid(&conn->acceptmbox)) {
-    /* use trypost to preven deadlock */
-    sys_mbox_trypost(&conn->acceptmbox, NULL);
-  }
-
-  if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
-      (old_state == NETCONN_CONNECT)) {
-    /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary
-       since the pcb has already been deleted! */
-    int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
-    SET_NONBLOCKING_CONNECT(conn, 0);
-
-    if (!was_nonblocking_connect) {
-      sys_sem_t* op_completed_sem;
-      /* set error return code */
-      LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
-      conn->current_msg->err = err;
-      op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
-      LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem));
-      conn->current_msg = NULL;
-      /* wake up the waiting task */
-      NETCONN_SET_SAFE_ERR(conn, err);
-      sys_sem_signal(op_completed_sem);
-    }
-  } else {
-    LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
-  }
-}
-
-/**
- * Setup a tcp_pcb with the correct callback function pointers
- * and their arguments.
- *
- * @param conn the TCP netconn to setup
- */
-static void
-setup_tcp(struct netconn *conn)
-{
-  struct tcp_pcb *pcb;
-
-  pcb = conn->pcb.tcp;
-  tcp_arg(pcb, conn);
-  tcp_recv(pcb, recv_tcp);
-  tcp_sent(pcb, sent_tcp);
-  tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL);
-  tcp_err(pcb, err_tcp);
-}
-
-/**
- * Accept callback function for TCP netconns.
- * Allocates a new netconn and posts that to conn->acceptmbox.
- *
- * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
- */
-static err_t
-accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
-{
-  struct netconn *newconn;
-  struct netconn *conn = (struct netconn *)arg;
-
-  LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-  if (!sys_mbox_valid(&conn->acceptmbox)) {
-    LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
-    return ERR_VAL;
-  }
-
-  if (newpcb == NULL) {
-    /* out-of-pcbs during connect: pass on this error to the application */
-    if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) {
-      /* Register event with callback */
-      API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
-    }
-    return ERR_VAL;
-  }
-
-  /* We have to set the callback here even though
-   * the new socket is unknown. newconn->socket is marked as -1. */
-  newconn = netconn_alloc(conn->type, conn->callback);
-  if (newconn == NULL) {
-    /* outof netconns: pass on this error to the application */
-    if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) {
-      /* Register event with callback */
-      API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
-    }
-    return ERR_MEM;
-  }
-  newconn->pcb.tcp = newpcb;
-  setup_tcp(newconn);
-  /* no protection: when creating the pcb, the netconn is not yet known
-     to the application thread */
-  newconn->last_err = err;
-
-  /* handle backlog counter */
-  tcp_backlog_delayed(newpcb);
-
-  if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
-    /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
-       so do nothing here! */
-    /* remove all references to this netconn from the pcb */
-    struct tcp_pcb* pcb = newconn->pcb.tcp;
-    tcp_arg(pcb, NULL);
-    tcp_recv(pcb, NULL);
-    tcp_sent(pcb, NULL);
-    tcp_poll(pcb, NULL, 0);
-    tcp_err(pcb, NULL);
-    /* remove reference from to the pcb from this netconn */
-    newconn->pcb.tcp = NULL;
-    /* no need to drain since we know the recvmbox is empty. */
-    sys_mbox_free(&newconn->recvmbox);
-    sys_mbox_set_invalid(&newconn->recvmbox);
-    netconn_free(newconn);
-    return ERR_MEM;
-  } else {
-    /* Register event with callback */
-    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
-  }
-
-  return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Create a new pcb of a specific type.
- * Called from lwip_netconn_do_newconn().
- *
- * @param msg the api_msg_msg describing the connection type
- */
-static void
-pcb_new(struct api_msg *msg)
-{
-  LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
-
-  /* Allocate a PCB for this connection */
-  switch(NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-  case NETCONN_RAW:
-    msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
-    if (msg->conn->pcb.raw != NULL) {
-      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
-    }
-    break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-  case NETCONN_UDP:
-    msg->conn->pcb.udp = udp_new();
-    if (msg->conn->pcb.udp != NULL) {
-#if LWIP_UDPLITE
-      if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
-        udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
-      }
-#endif /* LWIP_UDPLITE */
-      if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) {
-        udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
-      }
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-    }
-    break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-  case NETCONN_TCP:
-    msg->conn->pcb.tcp = tcp_new();
-    if (msg->conn->pcb.tcp != NULL) {
-      setup_tcp(msg->conn);
-    }
-    break;
-#endif /* LWIP_TCP */
-  default:
-    /* Unsupported netconn type, e.g. protocol disabled */
-    msg->err = ERR_VAL;
-    return;
-  }
-  if (msg->conn->pcb.ip == NULL) {
-    msg->err = ERR_MEM;
-  }
-#if LWIP_IPV4 && LWIP_IPV6
-  else {
-    if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
-      /* Convert IPv4 PCB manually to an IPv6 PCB */
-      IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip,  IPADDR_TYPE_V6);
-      IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
-    }
-  }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-}
-
-/**
- * Create a new pcb of a specific type inside a netconn.
- * Called from netconn_new_with_proto_and_callback.
- *
- * @param m the api_msg_msg describing the connection type
- */
-void
-lwip_netconn_do_newconn(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  msg->err = ERR_OK;
-  if (msg->conn->pcb.tcp == NULL) {
-    pcb_new(msg);
-  }
-  /* Else? This "new" connection already has a PCB allocated. */
-  /* Is this an error condition? Should it be deleted? */
-  /* We currently just are happy and return. */
-
-  TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Create a new netconn (of a specific type) that has a callback function.
- * The corresponding pcb is NOT created!
- *
- * @param t the type of 'connection' to create (@see enum netconn_type)
- * @param callback a function to call on status changes (RX available, TX'ed)
- * @return a newly allocated struct netconn or
- *         NULL on memory error
- */
-struct netconn*
-netconn_alloc(enum netconn_type t, netconn_callback callback)
-{
-  struct netconn *conn;
-  int size;
-
-  conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
-  if (conn == NULL) {
-    return NULL;
-  }
-
-  conn->last_err = ERR_OK;
-  conn->type = t;
-  conn->pcb.tcp = NULL;
-
-  /* If all sizes are the same, every compiler should optimize this switch to nothing */
-  switch(NETCONNTYPE_GROUP(t)) {
-#if LWIP_RAW
-  case NETCONN_RAW:
-    size = DEFAULT_RAW_RECVMBOX_SIZE;
-    break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-  case NETCONN_UDP:
-    size = DEFAULT_UDP_RECVMBOX_SIZE;
-    break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-  case NETCONN_TCP:
-    size = DEFAULT_TCP_RECVMBOX_SIZE;
-    break;
-#endif /* LWIP_TCP */
-  default:
-    LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);
-    goto free_and_return;
-  }
-
-  if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
-    goto free_and_return;
-  }
-#if !LWIP_NETCONN_SEM_PER_THREAD
-  if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
-    sys_mbox_free(&conn->recvmbox);
-    goto free_and_return;
-  }
-#endif
-
-#if LWIP_TCP
-  sys_mbox_set_invalid(&conn->acceptmbox);
-#endif
-  conn->state        = NETCONN_NONE;
-#if LWIP_SOCKET
-  /* initialize socket to -1 since 0 is a valid socket */
-  conn->socket       = -1;
-#endif /* LWIP_SOCKET */
-  conn->callback     = callback;
-#if LWIP_TCP
-  conn->current_msg  = NULL;
-  conn->write_offset = 0;
-#endif /* LWIP_TCP */
-#if LWIP_SO_SNDTIMEO
-  conn->send_timeout = 0;
-#endif /* LWIP_SO_SNDTIMEO */
-#if LWIP_SO_RCVTIMEO
-  conn->recv_timeout = 0;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
-  conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
-  conn->recv_avail   = 0;
-#endif /* LWIP_SO_RCVBUF */
-#if LWIP_SO_LINGER
-  conn->linger = -1;
-#endif /* LWIP_SO_LINGER */
-  conn->flags = 0;
-  return conn;
-free_and_return:
-  memp_free(MEMP_NETCONN, conn);
-  return NULL;
-}
-
-/**
- * Delete a netconn and all its resources.
- * The pcb is NOT freed (since we might not be in the right thread context do this).
- *
- * @param conn the netconn to free
- */
-void
-netconn_free(struct netconn *conn)
-{
-  LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
-  LWIP_ASSERT("recvmbox must be deallocated before calling this function",
-    !sys_mbox_valid(&conn->recvmbox));
-#if LWIP_TCP
-  LWIP_ASSERT("acceptmbox must be deallocated before calling this function",
-    !sys_mbox_valid(&conn->acceptmbox));
-#endif /* LWIP_TCP */
-
-#if !LWIP_NETCONN_SEM_PER_THREAD
-  sys_sem_free(&conn->op_completed);
-  sys_sem_set_invalid(&conn->op_completed);
-#endif
-
-  memp_free(MEMP_NETCONN, conn);
-}
-
-/**
- * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in
- * these mboxes
- *
- * @param conn the netconn to free
- * @bytes_drained bytes drained from recvmbox
- * @accepts_drained pending connections drained from acceptmbox
- */
-static void
-netconn_drain(struct netconn *conn)
-{
-  void *mem;
-#if LWIP_TCP
-  struct pbuf *p;
-#endif /* LWIP_TCP */
-
-  /* This runs in tcpip_thread, so we don't need to lock against rx packets */
-
-  /* Delete and drain the recvmbox. */
-  if (sys_mbox_valid(&conn->recvmbox)) {
-    while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
-#if LWIP_TCP
-      if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
-        if (mem != NULL) {
-          p = (struct pbuf*)mem;
-          /* pcb might be set to NULL already by err_tcp() */
-          if (conn->pcb.tcp != NULL) {
-            tcp_recved(conn->pcb.tcp, p->tot_len);
-          }
-          pbuf_free(p);
-        }
-      } else
-#endif /* LWIP_TCP */
-      {
-        netbuf_delete((struct netbuf *)mem);
-      }
-    }
-    sys_mbox_free(&conn->recvmbox);
-    sys_mbox_set_invalid(&conn->recvmbox);
-  }
-
-  /* Delete and drain the acceptmbox. */
-#if LWIP_TCP
-  if (sys_mbox_valid(&conn->acceptmbox)) {
-    while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
-      if (mem != &netconn_aborted) {
-        struct netconn *newconn = (struct netconn *)mem;
-        /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
-        /* pcb might be set to NULL already by err_tcp() */
-        /* drain recvmbox */
-        netconn_drain(newconn);
-        if (newconn->pcb.tcp != NULL) {
-          tcp_abort(newconn->pcb.tcp);
-          newconn->pcb.tcp = NULL;
-        }
-        netconn_free(newconn);
-      }
-    }
-    sys_mbox_free(&conn->acceptmbox);
-    sys_mbox_set_invalid(&conn->acceptmbox);
-  }
-#endif /* LWIP_TCP */
-}
-
-#if LWIP_TCP
-/**
- * Internal helper function to close a TCP netconn: since this sometimes
- * doesn't work at the first attempt, this function is called from multiple
- * places.
- *
- * @param conn the TCP netconn to close
- */
-static err_t
-lwip_netconn_do_close_internal(struct netconn *conn  WRITE_DELAYED_PARAM)
-{
-  err_t err;
-  u8_t shut, shut_rx, shut_tx, close;
-  u8_t close_finished = 0;
-  struct tcp_pcb* tpcb;
-#if LWIP_SO_LINGER
-  u8_t linger_wait_required = 0;
-#endif /* LWIP_SO_LINGER */
-
-  LWIP_ASSERT("invalid conn", (conn != NULL));
-  LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP));
-  LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
-  LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
-  LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
-
-  tpcb = conn->pcb.tcp;
-  shut = conn->current_msg->msg.sd.shut;
-  shut_rx = shut & NETCONN_SHUT_RD;
-  shut_tx = shut & NETCONN_SHUT_WR;
-  /* shutting down both ends is the same as closing
-     (also if RD or WR side was shut down before already) */
-  if (shut == NETCONN_SHUT_RDWR) {
-    close = 1;
-  } else if (shut_rx &&
-             ((tpcb->state == FIN_WAIT_1) ||
-              (tpcb->state == FIN_WAIT_2) ||
-              (tpcb->state == CLOSING))) {
-    close = 1;
-  } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) {
-    close = 1;
-  } else {
-    close = 0;
-  }
-
-  /* Set back some callback pointers */
-  if (close) {
-    tcp_arg(tpcb, NULL);
-  }
-  if (tpcb->state == LISTEN) {
-    tcp_accept(tpcb, NULL);
-  } else {
-    /* some callbacks have to be reset if tcp_close is not successful */
-    if (shut_rx) {
-      tcp_recv(tpcb, NULL);
-      tcp_accept(tpcb, NULL);
-    }
-    if (shut_tx) {
-      tcp_sent(tpcb, NULL);
-    }
-    if (close) {
-      tcp_poll(tpcb, NULL, 0);
-      tcp_err(tpcb, NULL);
-    }
-  }
-  /* Try to close the connection */
-  if (close) {
-#if LWIP_SO_LINGER
-    /* check linger possibilites before calling tcp_close */
-    err = ERR_OK;
-    /* linger enabled/required at all? (i.e. is there untransmitted data left?) */
-    if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
-      if ((conn->linger == 0)) {
-        /* data left but linger prevents waiting */
-        tcp_abort(tpcb);
-        tpcb = NULL;
-      } else if (conn->linger > 0) {
-        /* data left and linger says we should wait */
-        if (netconn_is_nonblocking(conn)) {
-          /* data left on a nonblocking netconn -> cannot linger */
-          err = ERR_WOULDBLOCK;
-        } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >=
-          (conn->linger * 1000)) {
-          /* data left but linger timeout has expired (this happens on further
-             calls to this function through poll_tcp */
-          tcp_abort(tpcb);
-          tpcb = NULL;
-        } else {
-          /* data left -> need to wait for ACK after successful close */
-          linger_wait_required = 1;
-        }
-      }
-    }
-    if ((err == ERR_OK) && (tpcb != NULL))
-#endif /* LWIP_SO_LINGER */
-    {
-      err = tcp_close(tpcb);
-    }
-  } else {
-    err = tcp_shutdown(tpcb, shut_rx, shut_tx);
-  }
-  if (err == ERR_OK) {
-    close_finished = 1;
-#if LWIP_SO_LINGER
-    if (linger_wait_required) {
-      /* wait for ACK of all unsent/unacked data by just getting called again */
-      close_finished = 0;
-      err = ERR_INPROGRESS;
-    }
-#endif /* LWIP_SO_LINGER */
-  } else {
-    if (err == ERR_MEM) {
-      /* Closing failed because of memory shortage, try again later. Even for
-         nonblocking netconns, we have to wait since no standard socket application
-         is prepared for close failing because of resource shortage.
-         Check the timeout: this is kind of an lwip addition to the standard sockets:
-         we wait for some time when failing to allocate a segment for the FIN */
-#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
-      s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT;
-#if LWIP_SO_SNDTIMEO
-      if (conn->send_timeout > 0) {
-        close_timeout = conn->send_timeout;
-      }
-#endif /* LWIP_SO_SNDTIMEO */
-#if LWIP_SO_LINGER
-      if (conn->linger >= 0) {
-        /* use linger timeout (seconds) */
-        close_timeout = conn->linger * 1000U;
-      }
-#endif
-      if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) {
-#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-      if (conn->current_msg->msg.sd.polls_left == 0) {
-#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-        close_finished = 1;
-        if (close) {
-          /* in this case, we want to RST the connection */
-          tcp_abort(tpcb);
-          err = ERR_OK;
-        }
-      }
-    } else {
-      /* Closing failed for a non-memory error: give up */
-      close_finished = 1;
-    }
-  }
-  if (close_finished) {
-    /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */
-    sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
-    conn->current_msg->err = err;
-    conn->current_msg = NULL;
-    conn->state = NETCONN_NONE;
-    if (err == ERR_OK) {
-      if (close) {
-        /* Set back some callback pointers as conn is going away */
-        conn->pcb.tcp = NULL;
-        /* Trigger select() in socket layer. Make sure everybody notices activity
-         on the connection, error first! */
-        API_EVENT(conn, NETCONN_EVT_ERROR, 0);
-      }
-      if (shut_rx) {
-        API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
-      }
-      if (shut_tx) {
-        API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
-      }
-    }
-    NETCONN_SET_SAFE_ERR(conn, err);
-#if LWIP_TCPIP_CORE_LOCKING
-    if (delayed)
-#endif
-    {
-      /* wake up the application task */
-      sys_sem_signal(op_completed_sem);
-    }
-    return ERR_OK;
-  }
-  if (!close_finished) {
-    /* Closing failed and we want to wait: restore some of the callbacks */
-    /* Closing of listen pcb will never fail! */
-    LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN));
-    if (shut_tx) {
-      tcp_sent(tpcb, sent_tcp);
-    }
-    /* when waiting for close, set up poll interval to 500ms */
-    tcp_poll(tpcb, poll_tcp, 1);
-    tcp_err(tpcb, err_tcp);
-    tcp_arg(tpcb, conn);
-    /* don't restore recv callback: we don't want to receive any more data */
-  }
-  /* If closing didn't succeed, we get called again either
-     from poll_tcp or from sent_tcp */
-  LWIP_ASSERT("err != ERR_OK", err != ERR_OK);
-  return err;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Delete the pcb inside a netconn.
- * Called from netconn_delete.
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_delconn(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  enum netconn_state state = msg->conn->state;
-  LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */
-    (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP));
-#if LWIP_NETCONN_FULLDUPLEX
-  /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */
-  if (state != NETCONN_NONE) {
-    if ((state == NETCONN_WRITE) ||
-        ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
-      /* close requested, abort running write/connect */
-      sys_sem_t* op_completed_sem;
-      LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
-      op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
-      msg->conn->current_msg->err = ERR_CLSD;
-      msg->conn->current_msg = NULL;
-      msg->conn->write_offset = 0;
-      msg->conn->state = NETCONN_NONE;
-      NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
-      sys_sem_signal(op_completed_sem);
-    }
-  }
-#else /* LWIP_NETCONN_FULLDUPLEX */
-  if (((state != NETCONN_NONE) &&
-       (state != NETCONN_LISTEN) &&
-       (state != NETCONN_CONNECT)) ||
-      ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
-    /* This means either a blocking write or blocking connect is running
-       (nonblocking write returns and sets state to NONE) */
-    msg->err = ERR_INPROGRESS;
-  } else
-#endif /* LWIP_NETCONN_FULLDUPLEX */
-  {
-    LWIP_ASSERT("blocking connect in progress",
-      (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
-    msg->err = ERR_OK;
-    /* Drain and delete mboxes */
-    netconn_drain(msg->conn);
-
-    if (msg->conn->pcb.tcp != NULL) {
-
-      switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-      case NETCONN_RAW:
-        raw_remove(msg->conn->pcb.raw);
-        break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-      case NETCONN_UDP:
-        msg->conn->pcb.udp->recv_arg = NULL;
-        udp_remove(msg->conn->pcb.udp);
-        break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-      case NETCONN_TCP:
-        LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
-          msg->conn->write_offset == 0);
-        msg->conn->state = NETCONN_CLOSE;
-        msg->msg.sd.shut = NETCONN_SHUT_RDWR;
-        msg->conn->current_msg = msg;
-#if LWIP_TCPIP_CORE_LOCKING
-        if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) {
-          LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE);
-          UNLOCK_TCPIP_CORE();
-          sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
-          LOCK_TCPIP_CORE();
-          LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
-        }
-#else /* LWIP_TCPIP_CORE_LOCKING */
-        lwip_netconn_do_close_internal(msg->conn);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-        /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing
-           the application thread, so we can return at this point! */
-        return;
-#endif /* LWIP_TCP */
-      default:
-        break;
-      }
-      msg->conn->pcb.tcp = NULL;
-    }
-    /* tcp netconns don't come here! */
-
-    /* @todo: this lets select make the socket readable and writable,
-       which is wrong! errfd instead? */
-    API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
-    API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
-  }
-  if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) {
-    TCPIP_APIMSG_ACK(msg);
-  }
-}
-
-/**
- * Bind a pcb contained in a netconn
- * Called from netconn_bind.
- *
- * @param m the api_msg_msg pointing to the connection and containing
- *          the IP address and port to bind to
- */
-void
-lwip_netconn_do_bind(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (ERR_IS_FATAL(msg->conn->last_err)) {
-    msg->err = msg->conn->last_err;
-  } else {
-    msg->err = ERR_VAL;
-    if (msg->conn->pcb.tcp != NULL) {
-      const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr);
-
-#if LWIP_IPV4 && LWIP_IPV6
-      /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
-       * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
-       */
-      if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) &&
-          (netconn_get_ipv6only(msg->conn) == 0)) {
-        /* change PCB type to IPADDR_TYPE_ANY */
-        IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip,  IPADDR_TYPE_ANY);
-        IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
-        
-        /* bind to IPADDR_TYPE_ANY */
-        ipaddr = IP_ANY_TYPE;
-      }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-      switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-      case NETCONN_RAW:
-        msg->err = raw_bind(msg->conn->pcb.raw, ipaddr);
-        break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-      case NETCONN_UDP:
-        msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port);
-        break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-      case NETCONN_TCP:
-        msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port);
-        break;
-#endif /* LWIP_TCP */
-      default:
-        break;
-      }
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_TCP
-/**
- * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has
- * been established (or reset by the remote host).
- *
- * @see tcp.h (struct tcp_pcb.connected) for parameters and return values
- */
-static err_t
-lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
-{
-  struct netconn *conn;
-  int was_blocking;
-  sys_sem_t* op_completed_sem = NULL;
-
-  LWIP_UNUSED_ARG(pcb);
-
-  conn = (struct netconn *)arg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
-  LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
-    (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
-
-  if (conn->current_msg != NULL) {
-    conn->current_msg->err = err;
-    op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
-  }
-  if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) {
-    setup_tcp(conn);
-  }
-  was_blocking = !IN_NONBLOCKING_CONNECT(conn);
-  SET_NONBLOCKING_CONNECT(conn, 0);
-  LWIP_ASSERT("blocking connect state error",
-    (was_blocking && op_completed_sem != NULL) ||
-    (!was_blocking && op_completed_sem == NULL));
-  conn->current_msg = NULL;
-  conn->state = NETCONN_NONE;
-  NETCONN_SET_SAFE_ERR(conn, ERR_OK);
-  API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
-
-  if (was_blocking) {
-    sys_sem_signal(op_completed_sem);
-  }
-  return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Connect a pcb contained inside a netconn
- * Called from netconn_connect.
- *
- * @param m the api_msg_msg pointing to the connection and containing
- *          the IP address and port to connect to
- */
-void
-lwip_netconn_do_connect(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (msg->conn->pcb.tcp == NULL) {
-    /* This may happen when calling netconn_connect() a second time */
-    msg->err = ERR_CLSD;
-  } else {
-    switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
-      break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-    case NETCONN_UDP:
-      msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-    case NETCONN_TCP:
-      /* Prevent connect while doing any other action. */
-      if (msg->conn->state == NETCONN_CONNECT) {
-        msg->err = ERR_ALREADY;
-      } else if (msg->conn->state != NETCONN_NONE) {
-        msg->err = ERR_ISCONN;
-      } else {
-        setup_tcp(msg->conn);
-        msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr),
-          msg->msg.bc.port, lwip_netconn_do_connected);
-        if (msg->err == ERR_OK) {
-          u8_t non_blocking = netconn_is_nonblocking(msg->conn);
-          msg->conn->state = NETCONN_CONNECT;
-          SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
-          if (non_blocking) {
-            msg->err = ERR_INPROGRESS;
-          } else {
-            msg->conn->current_msg = msg;
-            /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()),
-               when the connection is established! */
-#if LWIP_TCPIP_CORE_LOCKING
-            LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT);
-            UNLOCK_TCPIP_CORE();
-            sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
-            LOCK_TCPIP_CORE();
-            LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-            return;
-          }
-        }
-      }
-      break;
-#endif /* LWIP_TCP */
-    default:
-      LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0));
-      break;
-    }
-  }
-  /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(),
-     so use TCPIP_APIMSG_ACK() here. */
-  TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Disconnect a pcb contained inside a netconn
- * Only used for UDP netconns.
- * Called from netconn_disconnect.
- *
- * @param m the api_msg_msg pointing to the connection to disconnect
- */
-void
-lwip_netconn_do_disconnect(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-#if LWIP_UDP
-  if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
-    udp_disconnect(msg->conn->pcb.udp);
-    msg->err = ERR_OK;
-  } else
-#endif /* LWIP_UDP */
-  {
-    msg->err = ERR_VAL;
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_TCP
-/**
- * Set a TCP pcb contained in a netconn into listen mode
- * Called from netconn_listen.
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_listen(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (ERR_IS_FATAL(msg->conn->last_err)) {
-    msg->err = msg->conn->last_err;
-  } else {
-    msg->err = ERR_CONN;
-    if (msg->conn->pcb.tcp != NULL) {
-      if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
-        if (msg->conn->state == NETCONN_NONE) {
-          struct tcp_pcb* lpcb;
-          if (msg->conn->pcb.tcp->state != CLOSED) {
-            /* connection is not closed, cannot listen */
-            msg->err = ERR_VAL;
-          } else {
-#if LWIP_IPV4 && LWIP_IPV6
-            /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
-             * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
-             */
-            if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) &&
-                (netconn_get_ipv6only(msg->conn) == 0)) {
-              /* change PCB type to IPADDR_TYPE_ANY */
-              IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip,  IPADDR_TYPE_ANY);
-              IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY);
-            }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-#if TCP_LISTEN_BACKLOG
-            lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
-#else  /* TCP_LISTEN_BACKLOG */
-            lpcb = tcp_listen(msg->conn->pcb.tcp);
-#endif /* TCP_LISTEN_BACKLOG */
-
-            if (lpcb == NULL) {
-              /* in this case, the old pcb is still allocated */
-              msg->err = ERR_MEM;
-            } else {
-              /* delete the recvmbox and allocate the acceptmbox */
-              if (sys_mbox_valid(&msg->conn->recvmbox)) {
-                /** @todo: should we drain the recvmbox here? */
-                sys_mbox_free(&msg->conn->recvmbox);
-                sys_mbox_set_invalid(&msg->conn->recvmbox);
-              }
-              msg->err = ERR_OK;
-              if (!sys_mbox_valid(&msg->conn->acceptmbox)) {
-                msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
-              }
-              if (msg->err == ERR_OK) {
-                msg->conn->state = NETCONN_LISTEN;
-                msg->conn->pcb.tcp = lpcb;
-                tcp_arg(msg->conn->pcb.tcp, msg->conn);
-                tcp_accept(msg->conn->pcb.tcp, accept_function);
-              } else {
-                /* since the old pcb is already deallocated, free lpcb now */
-                tcp_close(lpcb);
-                msg->conn->pcb.tcp = NULL;
-              }
-            }
-          }
-        } else if (msg->conn->state == NETCONN_LISTEN) {
-          /* already listening, allow updating of the backlog */
-          msg->err = ERR_OK;
-          tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog);
-        }
-      } else {
-        msg->err = ERR_ARG;
-      }
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-#endif /* LWIP_TCP */
-
-/**
- * Send some data on a RAW or UDP pcb contained in a netconn
- * Called from netconn_send
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_send(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (ERR_IS_FATAL(msg->conn->last_err)) {
-    msg->err = msg->conn->last_err;
-  } else {
-    msg->err = ERR_CONN;
-    if (msg->conn->pcb.tcp != NULL) {
-      switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-      case NETCONN_RAW:
-        if (ip_addr_isany(&msg->msg.b->addr)) {
-          msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
-        } else {
-          msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
-        }
-        break;
-#endif
-#if LWIP_UDP
-      case NETCONN_UDP:
-#if LWIP_CHECKSUM_ON_COPY
-        if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
-          msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
-            msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
-        } else {
-          msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
-            &msg->msg.b->addr, msg->msg.b->port,
-            msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
-        }
-#else /* LWIP_CHECKSUM_ON_COPY */
-        if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
-          msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
-        } else {
-          msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
-        }
-#endif /* LWIP_CHECKSUM_ON_COPY */
-        break;
-#endif /* LWIP_UDP */
-      default:
-        break;
-      }
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_TCP
-/**
- * Indicate data has been received from a TCP pcb contained in a netconn
- * Called from netconn_recv
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_recv(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  msg->err = ERR_OK;
-  if (msg->conn->pcb.tcp != NULL) {
-    if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
-      u32_t remaining = msg->msg.r.len;
-      do {
-        u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
-        tcp_recved(msg->conn->pcb.tcp, recved);
-        remaining -= recved;
-      } while (remaining != 0);
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-#if TCP_LISTEN_BACKLOG
-/** Indicate that a TCP pcb has been accepted
- * Called from netconn_accept
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_accepted(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  msg->err = ERR_OK;
-  if (msg->conn->pcb.tcp != NULL) {
-    if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
-      tcp_backlog_accepted(msg->conn->pcb.tcp);
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-#endif /* TCP_LISTEN_BACKLOG */
-
-/**
- * See if more data needs to be written from a previous call to netconn_write.
- * Called initially from lwip_netconn_do_write. If the first call can't send all data
- * (because of low memory or empty send-buffer), this function is called again
- * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
- * blocking application thread (waiting in netconn_write) is released.
- *
- * @param conn netconn (that is currently in state NETCONN_WRITE) to process
- * @return ERR_OK
- *         ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
- */
-static err_t
-lwip_netconn_do_writemore(struct netconn *conn  WRITE_DELAYED_PARAM)
-{
-  err_t err;
-  const void *dataptr;
-  u16_t len, available;
-  u8_t write_finished = 0;
-  size_t diff;
-  u8_t dontblock;
-  u8_t apiflags;
-
-  LWIP_ASSERT("conn != NULL", conn != NULL);
-  LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
-  LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
-  LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
-  LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
-    conn->write_offset < conn->current_msg->msg.w.len);
-
-  apiflags = conn->current_msg->msg.w.apiflags;
-  dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
-
-#if LWIP_SO_SNDTIMEO
-  if ((conn->send_timeout != 0) &&
-      ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) {
-    write_finished = 1;
-    if (conn->write_offset == 0) {
-      /* nothing has been written */
-      err = ERR_WOULDBLOCK;
-      conn->current_msg->msg.w.len = 0;
-    } else {
-      /* partial write */
-      err = ERR_OK;
-      conn->current_msg->msg.w.len = conn->write_offset;
-      conn->write_offset = 0;
-    }
-  } else
-#endif /* LWIP_SO_SNDTIMEO */
-  {
-    dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
-    diff = conn->current_msg->msg.w.len - conn->write_offset;
-    if (diff > 0xffffUL) { /* max_u16_t */
-      len = 0xffff;
-      apiflags |= TCP_WRITE_FLAG_MORE;
-    } else {
-      len = (u16_t)diff;
-    }
-    available = tcp_sndbuf(conn->pcb.tcp);
-    if (available < len) {
-      /* don't try to write more than sendbuf */
-      len = available;
-      if (dontblock) {
-        if (!len) {
-          err = ERR_WOULDBLOCK;
-          goto err_mem;
-        }
-      } else {
-        apiflags |= TCP_WRITE_FLAG_MORE;
-      }
-    }
-    LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len));
-    err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
-    /* if OK or memory error, check available space */
-    if ((err == ERR_OK) || (err == ERR_MEM)) {
-err_mem:
-      if (dontblock && (len < conn->current_msg->msg.w.len)) {
-        /* non-blocking write did not write everything: mark the pcb non-writable
-           and let poll_tcp check writable space to mark the pcb writable again */
-        API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
-        conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
-      } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) ||
-                 (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) {
-        /* The queued byte- or pbuf-count exceeds the configured low-water limit,
-           let select mark this pcb as non-writable. */
-        API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
-      }
-    }
-
-    if (err == ERR_OK) {
-      err_t out_err;
-      conn->write_offset += len;
-      if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) {
-        /* return sent length */
-        conn->current_msg->msg.w.len = conn->write_offset;
-        /* everything was written */
-        write_finished = 1;
-      }
-      out_err = tcp_output(conn->pcb.tcp);
-      if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
-        /* If tcp_output fails with fatal error or no route is found,
-           don't try writing any more but return the error
-           to the application thread. */
-        err = out_err;
-        write_finished = 1;
-        conn->current_msg->msg.w.len = 0;
-      }
-    } else if ((err == ERR_MEM) && !dontblock) {
-      /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
-         we do NOT return to the application thread, since ERR_MEM is
-         only a temporary error! */
-
-      /* tcp_write returned ERR_MEM, try tcp_output anyway */
-      err_t out_err = tcp_output(conn->pcb.tcp);
-      if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
-        /* If tcp_output fails with fatal error or no route is found,
-           don't try writing any more but return the error
-           to the application thread. */
-        err = out_err;
-        write_finished = 1;
-        conn->current_msg->msg.w.len = 0;
-      }
-    } else {
-      /* On errors != ERR_MEM, we don't try writing any more but return
-         the error to the application thread. */
-      write_finished = 1;
-      conn->current_msg->msg.w.len = 0;
-    }
-  }
-  if (write_finished) {
-    /* everything was written: set back connection state
-       and back to application task */
-    sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
-    conn->current_msg->err = err;
-    conn->current_msg = NULL;
-    conn->write_offset = 0;
-    conn->state = NETCONN_NONE;
-    NETCONN_SET_SAFE_ERR(conn, err);
-#if LWIP_TCPIP_CORE_LOCKING
-    if (delayed)
-#endif
-    {
-      sys_sem_signal(op_completed_sem);
-    }
-  }
-#if LWIP_TCPIP_CORE_LOCKING
-  else {
-    return ERR_MEM;
-  }
-#endif
-  return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Send some data on a TCP pcb contained in a netconn
- * Called from netconn_write
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_write(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (ERR_IS_FATAL(msg->conn->last_err)) {
-    msg->err = msg->conn->last_err;
-  } else {
-    if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
-#if LWIP_TCP
-      if (msg->conn->state != NETCONN_NONE) {
-        /* netconn is connecting, closing or in blocking write */
-        msg->err = ERR_INPROGRESS;
-      } else if (msg->conn->pcb.tcp != NULL) {
-        msg->conn->state = NETCONN_WRITE;
-        /* set all the variables used by lwip_netconn_do_writemore */
-        LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
-          msg->conn->write_offset == 0);
-        LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0);
-        msg->conn->current_msg = msg;
-        msg->conn->write_offset = 0;
-#if LWIP_TCPIP_CORE_LOCKING
-        if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) {
-          LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
-          UNLOCK_TCPIP_CORE();
-          sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
-          LOCK_TCPIP_CORE();
-          LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE);
-        }
-#else /* LWIP_TCPIP_CORE_LOCKING */
-        lwip_netconn_do_writemore(msg->conn);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-        /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG
-           since lwip_netconn_do_writemore ACKs it! */
-        return;
-      } else {
-        msg->err = ERR_CONN;
-      }
-#else /* LWIP_TCP */
-      msg->err = ERR_VAL;
-#endif /* LWIP_TCP */
-#if (LWIP_UDP || LWIP_RAW)
-    } else {
-      msg->err = ERR_VAL;
-#endif /* (LWIP_UDP || LWIP_RAW) */
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Return a connection's local or remote address
- * Called from netconn_getaddr
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_getaddr(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (msg->conn->pcb.ip != NULL) {
-    if (msg->msg.ad.local) {
-      ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
-        msg->conn->pcb.ip->local_ip);
-    } else {
-      ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
-        msg->conn->pcb.ip->remote_ip);
-    }
-    msg->err = ERR_OK;
-    switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      if (msg->msg.ad.local) {
-        API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
-      } else {
-        /* return an error as connecting is only a helper for upper layers */
-        msg->err = ERR_CONN;
-      }
-      break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-    case NETCONN_UDP:
-      if (msg->msg.ad.local) {
-        API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
-      } else {
-        if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
-          msg->err = ERR_CONN;
-        } else {
-          API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
-        }
-      }
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-    case NETCONN_TCP:
-      if ((msg->msg.ad.local == 0) &&
-          ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) {
-        /* pcb is not connected and remote name is requested */
-        msg->err = ERR_CONN;
-      } else {
-        API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port);
-      }
-      break;
-#endif /* LWIP_TCP */
-    default:
-      LWIP_ASSERT("invalid netconn_type", 0);
-      break;
-    }
-  } else {
-    msg->err = ERR_CONN;
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Close or half-shutdown a TCP pcb contained in a netconn
- * Called from netconn_close
- * In contrast to closing sockets, the netconn is not deallocated.
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_close(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-#if LWIP_TCP
-  enum netconn_state state = msg->conn->state;
-  /* First check if this is a TCP netconn and if it is in a correct state
-      (LISTEN doesn't support half shutdown) */
-  if ((msg->conn->pcb.tcp != NULL) &&
-      (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) &&
-      ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) {
-    /* Check if we are in a connected state */
-    if (state == NETCONN_CONNECT) {
-      /* TCP connect in progress: cannot shutdown */
-      msg->err = ERR_CONN;
-    } else if (state == NETCONN_WRITE) {
-#if LWIP_NETCONN_FULLDUPLEX
-      if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
-        /* close requested, abort running write */
-        sys_sem_t* op_completed_sem;
-        LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
-        op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
-        msg->conn->current_msg->err = ERR_CLSD;
-        msg->conn->current_msg = NULL;
-        msg->conn->write_offset = 0;
-        msg->conn->state = NETCONN_NONE;
-        NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
-        sys_sem_signal(op_completed_sem);
-      } else {
-        LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
-        /* In this case, let the write continue and do not interfere with
-           conn->current_msg or conn->state! */
-        msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
-      }
-#else /* LWIP_NETCONN_FULLDUPLEX */
-      msg->err = ERR_INPROGRESS;
-#endif /* LWIP_NETCONN_FULLDUPLEX */
-    } else {
-      if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
-        /* Drain and delete mboxes */
-        netconn_drain(msg->conn);
-      }
-      LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
-        msg->conn->write_offset == 0);
-      msg->conn->state = NETCONN_CLOSE;
-      msg->conn->current_msg = msg;
-#if LWIP_TCPIP_CORE_LOCKING
-      if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) {
-        LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE);
-        UNLOCK_TCPIP_CORE();
-        sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
-        LOCK_TCPIP_CORE();
-        LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
-      }
-#else /* LWIP_TCPIP_CORE_LOCKING */
-      lwip_netconn_do_close_internal(msg->conn);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-      /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */
-      return;
-    }
-  } else
-#endif /* LWIP_TCP */
-  {
-    msg->err = ERR_CONN;
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
-/**
- * Join multicast groups for UDP netconns.
- * Called from netconn_join_leave_group
- *
- * @param m the api_msg_msg pointing to the connection
- */
-void
-lwip_netconn_do_join_leave_group(void *m)
-{
-  struct api_msg *msg = (struct api_msg*)m;
-
-  if (ERR_IS_FATAL(msg->conn->last_err)) {
-    msg->err = msg->conn->last_err;
-  } else {
-    if (msg->conn->pcb.tcp != NULL) {
-      if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
-#if LWIP_UDP
-#if LWIP_IPV6 && LWIP_IPV6_MLD
-        if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
-          if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
-            msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
-              ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
-          } else {
-            msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
-              ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
-          }
-        }
-        else
-#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
-        {
-#if LWIP_IGMP
-          if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
-            msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
-              ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
-          } else {
-            msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
-              ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
-          }
-#endif /* LWIP_IGMP */
-        }
-#endif /* LWIP_UDP */
-#if (LWIP_TCP || LWIP_RAW)
-      } else {
-        msg->err = ERR_VAL;
-#endif /* (LWIP_TCP || LWIP_RAW) */
-      }
-    } else {
-      msg->err = ERR_CONN;
-    }
-  }
-  TCPIP_APIMSG_ACK(msg);
-}
-#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
-
-#if LWIP_DNS
-/**
- * Callback function that is called when DNS name is resolved
- * (or on timeout). A waiting application thread is waked up by
- * signaling the semaphore.
- */
-static void
-lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg)
-{
-  struct dns_api_msg *msg = (struct dns_api_msg*)arg;
-
-  /* we trust the internal implementation to be correct :-) */
-  LWIP_UNUSED_ARG(name);
-
-  if (ipaddr == NULL) {
-    /* timeout or memory error */
-    API_EXPR_DEREF(msg->err) = ERR_VAL;
-  } else {
-    /* address was resolved */
-    API_EXPR_DEREF(msg->err) = ERR_OK;
-    API_EXPR_DEREF(msg->addr) = *ipaddr;
-  }
-  /* wake up the application task waiting in netconn_gethostbyname */
-  sys_sem_signal(API_EXPR_REF_SEM(msg->sem));
-}
-
-/**
- * Execute a DNS query
- * Called from netconn_gethostbyname
- *
- * @param arg the dns_api_msg pointing to the query
- */
-void
-lwip_netconn_do_gethostbyname(void *arg)
-{
-  struct dns_api_msg *msg = (struct dns_api_msg*)arg;
-  u8_t addrtype =
-#if LWIP_IPV4 && LWIP_IPV6
-    msg->dns_addrtype;
-#else
-    LWIP_DNS_ADDRTYPE_DEFAULT;
-#endif
-
-  API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name,
-    API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype);
-  if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) {
-    /* on error or immediate success, wake up the application
-     * task waiting in netconn_gethostbyname */
-    sys_sem_signal(API_EXPR_REF_SEM(msg->sem));
-  }
-}
-#endif /* LWIP_DNS */
-
-#endif /* LWIP_NETCONN */

+ 0 - 117
components/net/lwip-2.0.0/src/api/err.c

@@ -1,117 +0,0 @@
-/**
- * @file
- * Error Management module
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/err.h"
-#include "lwip/def.h"
-#include "lwip/sys.h"
-
-#include "lwip/errno.h"
-
-#if !NO_SYS
-/** Table to quickly map an lwIP error (err_t) to a socket error
-  * by using -err as an index */
-static const int err_to_errno_table[] = {
-  0,             /* ERR_OK          0      No error, everything OK. */
-  ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
-  ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
-  EWOULDBLOCK,   /* ERR_TIMEOUT    -3      Timeout                  */
-  EHOSTUNREACH,  /* ERR_RTE        -4      Routing problem.         */
-  EINPROGRESS,   /* ERR_INPROGRESS -5      Operation in progress    */
-  EINVAL,        /* ERR_VAL        -6      Illegal value.           */
-  EWOULDBLOCK,   /* ERR_WOULDBLOCK -7      Operation would block.   */
-  EADDRINUSE,    /* ERR_USE        -8      Address in use.          */
-  EALREADY,      /* ERR_ALREADY    -9      Already connecting.      */
-  EISCONN,       /* ERR_ISCONN     -10     Conn already established.*/
-  ENOTCONN,      /* ERR_CONN       -11     Not connected.           */
-  -1,            /* ERR_IF         -12     Low-level netif error    */
-  ECONNABORTED,  /* ERR_ABRT       -13     Connection aborted.      */
-  ECONNRESET,    /* ERR_RST        -14     Connection reset.        */
-  ENOTCONN,      /* ERR_CLSD       -15     Connection closed.       */
-  EIO            /* ERR_ARG        -16     Illegal argument.        */
-};
-#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 */
-
-#if !NO_SYS
-int
-err_to_errno(err_t err)
-{
-  if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
-    return EIO;
-  }
-  return err_to_errno_table[-err];
-}
-#endif /* !NO_SYS */

+ 0 - 246
components/net/lwip-2.0.0/src/api/netbuf.c

@@ -1,246 +0,0 @@
-/**
- * @file
- * Network buffer management
- *
- * @defgroup netbuf Network buffers
- * @ingroup netconn
- * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
- * to avoid copying data around.\n
- * Buffers must not be shared accross multiple threads, all functions except
- * netbuf_new() and netbuf_delete() are not thread-safe.
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/netbuf.h"
-#include "lwip/memp.h"
-
-#include <string.h>
-
-/**
- * @ingroup netbuf
- * Create (allocate) and initialize a new netbuf.
- * The netbuf doesn't yet contain a packet buffer!
- *
- * @return a pointer to a new netbuf
- *         NULL on lack of memory
- */
-struct
-netbuf *netbuf_new(void)
-{
-  struct netbuf *buf;
-
-  buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
-  if (buf != NULL) {
-    memset(buf, 0, sizeof(struct netbuf));
-  }
-  return buf;
-}
-
-/**
- * @ingroup netbuf
- * Deallocate a netbuf allocated by netbuf_new().
- *
- * @param buf pointer to a netbuf allocated by netbuf_new()
- */
-void
-netbuf_delete(struct netbuf *buf)
-{
-  if (buf != NULL) {
-    if (buf->p != NULL) {
-      pbuf_free(buf->p);
-      buf->p = buf->ptr = NULL;
-    }
-    memp_free(MEMP_NETBUF, buf);
-  }
-}
-
-/**
- * @ingroup netbuf
- * Allocate memory for a packet buffer for a given netbuf.
- *
- * @param buf the netbuf for which to allocate a packet buffer
- * @param size the size of the packet buffer to allocate
- * @return pointer to the allocated memory
- *         NULL if no memory could be allocated
- */
-void *
-netbuf_alloc(struct netbuf *buf, u16_t size)
-{
-  LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
-
-  /* Deallocate any previously allocated memory. */
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
-  if (buf->p == NULL) {
-     return NULL;
-  }
-  LWIP_ASSERT("check that first pbuf can hold size",
-             (buf->p->len >= size));
-  buf->ptr = buf->p;
-  return buf->p->payload;
-}
-
-/**
- * @ingroup netbuf
- * Free the packet buffer included in a netbuf
- *
- * @param buf pointer to the netbuf which contains the packet buffer to free
- */
-void
-netbuf_free(struct netbuf *buf)
-{
-  LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = buf->ptr = NULL;
-}
-
-/**
- * @ingroup netbuf
- * Let a netbuf reference existing (non-volatile) data.
- *
- * @param buf netbuf which should reference the data
- * @param dataptr pointer to the data to reference
- * @param size size of the data
- * @return ERR_OK if data is referenced
- *         ERR_MEM if data couldn't be referenced due to lack of memory
- */
-err_t
-netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
-{
-  LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
-  if (buf->p == NULL) {
-    buf->ptr = NULL;
-    return ERR_MEM;
-  }
-  ((struct pbuf_rom*)buf->p)->payload = dataptr;
-  buf->p->len = buf->p->tot_len = size;
-  buf->ptr = buf->p;
-  return ERR_OK;
-}
-
-/**
- * @ingroup netbuf
- * Chain one netbuf to another (@see pbuf_chain)
- *
- * @param head the first netbuf
- * @param tail netbuf to chain after head, freed by this function, may not be reference after returning
- */
-void
-netbuf_chain(struct netbuf *head, struct netbuf *tail)
-{
-  LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
-  LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
-  pbuf_cat(head->p, tail->p);
-  head->ptr = head->p;
-  memp_free(MEMP_NETBUF, tail);
-}
-
-/**
- * @ingroup netbuf
- * Get the data pointer and length of the data inside a netbuf.
- *
- * @param buf netbuf to get the data from
- * @param dataptr pointer to a void pointer where to store the data pointer
- * @param len pointer to an u16_t where the length of the data is stored
- * @return ERR_OK if the information was retrieved,
- *         ERR_BUF on error.
- */
-err_t
-netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
-{
-  LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
-  LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
-  LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
-
-  if (buf->ptr == NULL) {
-    return ERR_BUF;
-  }
-  *dataptr = buf->ptr->payload;
-  *len = buf->ptr->len;
-  return ERR_OK;
-}
-
-/**
- * @ingroup netbuf
- * Move the current data pointer of a packet buffer contained in a netbuf
- * to the next part.
- * The packet buffer itself is not modified.
- *
- * @param buf the netbuf to modify
- * @return -1 if there is no next part
- *         1  if moved to the next part but now there is no next part
- *         0  if moved to the next part and there are still more parts
- */
-s8_t
-netbuf_next(struct netbuf *buf)
-{
-  LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
-  if (buf->ptr->next == NULL) {
-    return -1;
-  }
-  buf->ptr = buf->ptr->next;
-  if (buf->ptr->next == NULL) {
-    return 1;
-  }
-  return 0;
-}
-
-/**
- * @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_first: invalid buf", (buf != NULL), return;);
-  buf->ptr = buf->p;
-}
-
-#endif /* LWIP_NETCONN */

+ 0 - 413
components/net/lwip-2.0.0/src/api/netdb.c

@@ -1,413 +0,0 @@
-/**
- * @file
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Simon Goldschmidt
- *
- */
-
-#include "lwip/netdb.h"
-
-#if LWIP_DNS && LWIP_SOCKET
-
-#include "lwip/err.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
-#include "lwip/ip_addr.h"
-#include "lwip/api.h"
-#include "lwip/dns.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-/** helper struct for gethostbyname_r to access the char* buffer */
-struct gethostbyname_r_helper {
-  ip_addr_t *addr_list[2];
-  ip_addr_t addr;
-  char *aliases;
-};
-
-/** h_errno is exported in netdb.h for access by applications. */
-#if LWIP_DNS_API_DECLARE_H_ERRNO
-int h_errno;
-#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
-
-/** define "hostent" variables storage: 0 if we use a static (but unprotected)
- * set of variables for lwip_gethostbyname, 1 if we use a local storage */
-#ifndef LWIP_DNS_API_HOSTENT_STORAGE
-#define LWIP_DNS_API_HOSTENT_STORAGE 0
-#endif
-
-/** define "hostent" variables storage */
-#if LWIP_DNS_API_HOSTENT_STORAGE
-#define HOSTENT_STORAGE
-#else
-#define HOSTENT_STORAGE static
-#endif /* LWIP_DNS_API_STATIC_HOSTENT */
-
-/**
- * Returns an entry containing addresses of address family AF_INET
- * for the host with name name.
- * Due to dns_gethostbyname limitations, only one address is returned.
- *
- * @param name the hostname to resolve
- * @return an entry containing addresses of address family AF_INET
- *         for the host with name name
- */
-struct hostent*
-lwip_gethostbyname(const char *name)
-{
-  err_t err;
-  ip_addr_t addr;
-
-  /* buffer variables for lwip_gethostbyname() */
-  HOSTENT_STORAGE struct hostent s_hostent;
-  HOSTENT_STORAGE char *s_aliases;
-  HOSTENT_STORAGE ip_addr_t s_hostent_addr;
-  HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
-  HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
-
-  /* query host IP address */
-  err = netconn_gethostbyname(name, &addr);
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
-    h_errno = HOST_NOT_FOUND;
-    return NULL;
-  }
-
-  /* fill hostent */
-  s_hostent_addr = addr;
-  s_phostent_addr[0] = &s_hostent_addr;
-  s_phostent_addr[1] = NULL;
-  strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
-  s_hostname[DNS_MAX_NAME_LENGTH] = 0;
-  s_hostent.h_name = s_hostname;
-  s_aliases = NULL;
-  s_hostent.h_aliases = &s_aliases;
-  s_hostent.h_addrtype = AF_INET;
-  s_hostent.h_length = sizeof(ip_addr_t);
-  s_hostent.h_addr_list = (char**)&s_phostent_addr;
-
-#if DNS_DEBUG
-  /* dump hostent */
-  LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name           == %s\n", s_hostent.h_name));
-  LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases        == %p\n", (void*)s_hostent.h_aliases));
-  /* h_aliases are always empty */
-  LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype       == %d\n", s_hostent.h_addrtype));
-  LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length         == %d\n", s_hostent.h_length));
-  LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list      == %p\n", (void*)s_hostent.h_addr_list));
-  if (s_hostent.h_addr_list != NULL) {
-    u8_t idx;
-    for (idx=0; s_hostent.h_addr_list[idx]; idx++) {
-      LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]   == %p\n", idx, s_hostent.h_addr_list[idx]));
-      LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
-    }
-  }
-#endif /* DNS_DEBUG */
-
-#if LWIP_DNS_API_HOSTENT_STORAGE
-  /* this function should return the "per-thread" hostent after copy from s_hostent */
-  return sys_thread_hostent(&s_hostent);
-#else
-  return &s_hostent;
-#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
-}
-
-/**
- * Thread-safe variant of lwip_gethostbyname: instead of using a static
- * buffer, this function takes buffer and errno pointers as arguments
- * and uses these for the result.
- *
- * @param name the hostname to resolve
- * @param ret pre-allocated struct where to store the result
- * @param buf pre-allocated buffer where to store additional data
- * @param buflen the size of buf
- * @param result pointer to a hostent pointer that is set to ret on success
- *               and set to zero on error
- * @param h_errnop pointer to an int where to store errors (instead of modifying
- *                 the global h_errno)
- * @return 0 on success, non-zero on error, additional error information
- *         is stored in *h_errnop instead of h_errno to be thread-safe
- */
-int
-lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
-                size_t buflen, struct hostent **result, int *h_errnop)
-{
-  err_t err;
-  struct gethostbyname_r_helper *h;
-  char *hostname;
-  size_t namelen;
-  int lh_errno;
-
-  if (h_errnop == NULL) {
-    /* ensure h_errnop is never NULL */
-    h_errnop = &lh_errno;
-  }
-
-  if (result == NULL) {
-    /* not all arguments given */
-    *h_errnop = EINVAL;
-    return -1;
-  }
-  /* first thing to do: set *result to nothing */
-  *result = NULL;
-  if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
-    /* not all arguments given */
-    *h_errnop = EINVAL;
-    return -1;
-  }
-
-  namelen = strlen(name);
-  if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
-    /* buf can't hold the data needed + a copy of name */
-    *h_errnop = ERANGE;
-    return -1;
-  }
-
-  h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
-  hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
-
-  /* query host IP address */
-  err = netconn_gethostbyname(name, &h->addr);
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
-    *h_errnop = HOST_NOT_FOUND;
-    return -1;
-  }
-
-  /* copy the hostname into buf */
-  MEMCPY(hostname, name, namelen);
-  hostname[namelen] = 0;
-
-  /* fill hostent */
-  h->addr_list[0] = &h->addr;
-  h->addr_list[1] = NULL;
-  h->aliases = NULL;
-  ret->h_name = hostname;
-  ret->h_aliases = &h->aliases;
-  ret->h_addrtype = AF_INET;
-  ret->h_length = sizeof(ip_addr_t);
-  ret->h_addr_list = (char**)&h->addr_list;
-
-  /* set result != NULL */
-  *result = ret;
-
-  /* return success */
-  return 0;
-}
-
-/**
- * Frees one or more addrinfo structures returned by getaddrinfo(), along with
- * any additional storage associated with those structures. If the ai_next field
- * of the structure is not null, the entire list of structures is freed.
- *
- * @param ai struct addrinfo to free
- */
-void
-lwip_freeaddrinfo(struct addrinfo *ai)
-{
-  struct addrinfo *next;
-
-  while (ai != NULL) {
-    next = ai->ai_next;
-    memp_free(MEMP_NETDB, ai);
-    ai = next;
-  }
-}
-
-/**
- * Translates the name of a service location (for example, a host name) and/or
- * a service name and returns a set of socket addresses and associated
- * information to be used in creating a socket with which to address the
- * specified service.
- * Memory for the result is allocated internally and must be freed by calling
- * lwip_freeaddrinfo()!
- *
- * Due to a limitation in dns_gethostbyname, only the first address of a
- * host is returned.
- * Also, service names are not supported (only port numbers)!
- *
- * @param nodename descriptive name or address string of the host
- *                 (may be NULL -> local address)
- * @param servname port number as string of NULL
- * @param hints structure containing input values that set socktype and protocol
- * @param res pointer to a pointer where to store the result (set to NULL on failure)
- * @return 0 on success, non-zero on failure
- *
- * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG
- */
-int
-lwip_getaddrinfo(const char *nodename, const char *servname,
-       const struct addrinfo *hints, struct addrinfo **res)
-{
-  err_t err;
-  ip_addr_t addr;
-  struct addrinfo *ai;
-  struct sockaddr_storage *sa = NULL;
-  int port_nr = 0;
-  size_t total_size;
-  size_t namelen = 0;
-  int ai_family;
-
-  if (res == NULL) {
-    return EAI_FAIL;
-  }
-  *res = NULL;
-  if ((nodename == NULL) && (servname == NULL)) {
-    return EAI_NONAME;
-  }
-
-  if (hints != NULL) {
-    ai_family = hints->ai_family;
-    if ((ai_family != AF_UNSPEC)
-#if LWIP_IPV4
-      && (ai_family != AF_INET)
-#endif /* LWIP_IPV4 */
-#if LWIP_IPV6
-      && (ai_family != AF_INET6)
-#endif /* LWIP_IPV6 */
-      ) {
-      return EAI_FAMILY;
-    }
-  } else {
-    ai_family = AF_UNSPEC;
-  }
-
-  if (servname != NULL) {
-    /* service name specified: convert to port number
-     * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
-    port_nr = atoi(servname);
-    if ((port_nr <= 0) || (port_nr > 0xffff)) {
-      return EAI_SERVICE;
-    }
-  }
-
-  if (nodename != NULL) {
-    /* service location specified, try to resolve */
-    if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
-      /* no DNS lookup, just parse for an address string */
-      if (!ipaddr_aton(nodename, &addr)) {
-        return EAI_NONAME;
-      }
-#if LWIP_IPV4 && LWIP_IPV6
-      if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
-          (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) {
-        return EAI_NONAME;
-      }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-    } else {
-#if LWIP_IPV4 && LWIP_IPV6
-      /* AF_UNSPEC: prefer IPv4 */
-      u8_t type = NETCONN_DNS_IPV4_IPV6;
-      if (ai_family == AF_INET) {
-        type = NETCONN_DNS_IPV4;
-      } else if (ai_family == AF_INET6) {
-        type = NETCONN_DNS_IPV6;
-      }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-      err = netconn_gethostbyname_addrtype(nodename, &addr, type);
-      if (err != ERR_OK) {
-        return EAI_FAIL;
-      }
-    }
-  } else {
-    /* service location specified, use loopback address */
-    if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
-      ip_addr_set_any(ai_family == AF_INET6, &addr);
-    } else {
-      ip_addr_set_loopback(ai_family == AF_INET6, &addr);
-    }
-  }
-
-  total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
-  if (nodename != NULL) {
-    namelen = strlen(nodename);
-    if (namelen > DNS_MAX_NAME_LENGTH) {
-      /* invalid name length */
-      return EAI_FAIL;
-    }
-    LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
-    total_size += namelen + 1;
-  }
-  /* If this fails, please report to lwip-devel! :-) */
-  LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
-    total_size <= NETDB_ELEM_SIZE);
-  ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
-  if (ai == NULL) {
-    return EAI_MEMORY;
-  }
-  memset(ai, 0, total_size);
-  /* cast through void* to get rid of alignment warnings */
-  sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo));
-  if (IP_IS_V6_VAL(addr)) {
-#if LWIP_IPV6
-    struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
-    /* set up sockaddr */
-    inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
-    sa6->sin6_family = AF_INET6;
-    sa6->sin6_len = sizeof(struct sockaddr_in6);
-    sa6->sin6_port = lwip_htons((u16_t)port_nr);
-    ai->ai_family = AF_INET6;
-#endif /* LWIP_IPV6 */
-  } else {
-#if LWIP_IPV4
-    struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
-    /* set up sockaddr */
-    inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
-    sa4->sin_family = AF_INET;
-    sa4->sin_len = sizeof(struct sockaddr_in);
-    sa4->sin_port = lwip_htons((u16_t)port_nr);
-    ai->ai_family = AF_INET;
-#endif /* LWIP_IPV4 */
-  }
-
-  /* set up addrinfo */
-  if (hints != NULL) {
-    /* copy socktype & protocol from hints if specified */
-    ai->ai_socktype = hints->ai_socktype;
-    ai->ai_protocol = hints->ai_protocol;
-  }
-  if (nodename != NULL) {
-    /* copy nodename to canonname if specified */
-    ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
-    MEMCPY(ai->ai_canonname, nodename, namelen);
-    ai->ai_canonname[namelen] = 0;
-  }
-  ai->ai_addrlen = sizeof(struct sockaddr_storage);
-  ai->ai_addr = (struct sockaddr*)sa;
-
-  *res = ai;
-
-  return 0;
-}
-
-#endif /* LWIP_DNS && LWIP_SOCKET */

+ 0 - 221
components/net/lwip-2.0.0/src/api/netifapi.c

@@ -1,221 +0,0 @@
-/**
- * @file
- * Network Interface Sequential API module
- *
- * @defgroup netifapi NETIF API
- * @ingroup sequential_api
- * Thread-safe functions to be called from non-TCPIP threads
- * 
- * @defgroup netifapi_netif NETIF related
- * @ingroup netifapi
- * To be called from non-TCPIP threads 
- */
-
-/*
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/netifapi.h"
-#include "lwip/memp.h"
-#include "lwip/priv/tcpip_priv.h"
-
-#define NETIFAPI_VAR_REF(name)      API_VAR_REF(name)
-#define NETIFAPI_VAR_DECLARE(name)  API_VAR_DECLARE(struct netifapi_msg, name)
-#define NETIFAPI_VAR_ALLOC(name)    API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, 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
-netifapi_do_netif_add(struct tcpip_api_call_data *m)
-{
-  /* cast through void* to silence alignment warnings. 
-   * We know it works because the structs have been instantiated as struct netifapi_msg */
-  struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
-  
-  if (!netif_add( msg->netif,
-#if LWIP_IPV4
-                  API_EXPR_REF(msg->msg.add.ipaddr),
-                  API_EXPR_REF(msg->msg.add.netmask),
-                  API_EXPR_REF(msg->msg.add.gw),
-#endif /* LWIP_IPV4 */
-                  msg->msg.add.state,
-                  msg->msg.add.init,
-                  msg->msg.add.input)) {
-    return ERR_IF;
-  } else {
-    return ERR_OK;
-  }
-}
-
-#if LWIP_IPV4
-/**
- * Call netif_set_addr() inside the tcpip_thread context.
- */
-static err_t
-netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
-{
-  /* cast through void* to silence alignment warnings. 
-   * We know it works because the structs have been instantiated as struct netifapi_msg */
-  struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
-
-  netif_set_addr( msg->netif,
-                  API_EXPR_REF(msg->msg.add.ipaddr),
-                  API_EXPR_REF(msg->msg.add.netmask),
-                  API_EXPR_REF(msg->msg.add.gw));
-  return ERR_OK;
-}
-#endif /* LWIP_IPV4 */
-
-/**
- * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
- * tcpip_thread context.
- */
-static err_t
-netifapi_do_netif_common(struct tcpip_api_call_data *m)
-{
-  /* cast through void* to silence alignment warnings. 
-   * We know it works because the structs have been instantiated as struct netifapi_msg */
-  struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
-
-  if (msg->msg.common.errtfunc != NULL) {
-    return msg->msg.common.errtfunc(msg->netif);
-  } 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.
- *
- * @note for params @see netif_add()
- */
-err_t
-netifapi_netif_add(struct netif *netif,
-#if LWIP_IPV4
-                   const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
-#endif /* LWIP_IPV4 */
-                   void *state, netif_init_fn init, netif_input_fn input)
-{
-  err_t err;
-  NETIFAPI_VAR_DECLARE(msg);
-  NETIFAPI_VAR_ALLOC(msg);
-
-#if LWIP_IPV4
-  if (ipaddr == NULL) {
-    ipaddr = IP4_ADDR_ANY4;
-  }
-  if (netmask == NULL) {
-    netmask = IP4_ADDR_ANY4;
-  }
-  if (gw == NULL) {
-    gw = IP4_ADDR_ANY4;
-  }
-#endif /* LWIP_IPV4 */
-
-  NETIFAPI_VAR_REF(msg).netif = netif;
-#if LWIP_IPV4
-  NETIFAPI_VAR_REF(msg).msg.add.ipaddr  = NETIFAPI_VAR_REF(ipaddr);
-  NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
-  NETIFAPI_VAR_REF(msg).msg.add.gw      = NETIFAPI_VAR_REF(gw);
-#endif /* LWIP_IPV4 */
-  NETIFAPI_VAR_REF(msg).msg.add.state   = state;
-  NETIFAPI_VAR_REF(msg).msg.add.init    = init;
-  NETIFAPI_VAR_REF(msg).msg.add.input   = input;
-  err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
-  NETIFAPI_VAR_FREE(msg);
-  return err;
-}
-
-#if LWIP_IPV4
-/**
- * @ingroup netifapi_netif
- * Call netif_set_addr() in a thread-safe way by running that function inside the
- * tcpip_thread context.
- *
- * @note for params @see netif_set_addr()
- */
-err_t
-netifapi_netif_set_addr(struct netif *netif,
-                        const ip4_addr_t *ipaddr,
-                        const ip4_addr_t *netmask,
-                        const ip4_addr_t *gw)
-{
-  err_t err;
-  NETIFAPI_VAR_DECLARE(msg);
-  NETIFAPI_VAR_ALLOC(msg);
-
-  if (ipaddr == NULL) {
-    ipaddr = IP4_ADDR_ANY4;
-  }
-  if (netmask == NULL) {
-    netmask = IP4_ADDR_ANY4;
-  }
-  if (gw == NULL) {
-    gw = IP4_ADDR_ANY4;
-  }
-
-  NETIFAPI_VAR_REF(msg).netif = netif;
-  NETIFAPI_VAR_REF(msg).msg.add.ipaddr  = NETIFAPI_VAR_REF(ipaddr);
-  NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
-  NETIFAPI_VAR_REF(msg).msg.add.gw      = NETIFAPI_VAR_REF(gw);
-  err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
-  NETIFAPI_VAR_FREE(msg);
-  return err;
-}
-#endif /* LWIP_IPV4 */
-
-/**
- * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
- * way by running that function inside the tcpip_thread context.
- *
- * @note use only for functions where there is only "netif" parameter.
- */
-err_t
-netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
-                       netifapi_errt_fn errtfunc)
-{
-  err_t err;
-  NETIFAPI_VAR_DECLARE(msg);
-  NETIFAPI_VAR_ALLOC(msg);
-
-  NETIFAPI_VAR_REF(msg).netif = netif;
-  NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
-  NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
-  err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
-  NETIFAPI_VAR_FREE(msg);
-  return err;
-}
-
-#endif /* LWIP_NETIF_API */

+ 0 - 2790
components/net/lwip-2.0.0/src/api/sockets.c

@@ -1,2790 +0,0 @@
-/**
- * @file
- * Sockets BSD-Like API module
- *
- * @defgroup socket Socket API
- * @ingroup sequential_api
- * BSD-style socket API.\n
- * Thread-safe, to be called from non-TCPIP threads only.\n
- * Can be activated by defining @ref LWIP_SOCKET to 1.\n
- * Header is in posix/sys/socket.h\b
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/sockets.h"
-#include "lwip/api.h"
-#include "lwip/sys.h"
-#include "lwip/igmp.h"
-#include "lwip/inet.h"
-#include "lwip/tcp.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/memp.h"
-#include "lwip/pbuf.h"
-#include "lwip/priv/tcpip_priv.h"
-#if LWIP_CHECKSUM_ON_COPY
-#include "lwip/inet_chksum.h"
-#endif
-
-#include <string.h>
-
-/* If the netconn API is not required publicly, then we include the necessary
-   files here to get the implementation */
-#if !LWIP_NETCONN
-#undef LWIP_NETCONN
-#define LWIP_NETCONN 1
-#include "api_msg.c"
-#include "api_lib.c"
-#include "netbuf.c"
-#undef LWIP_NETCONN
-#define LWIP_NETCONN 0
-#endif
-
-#if LWIP_IPV4
-#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
-      (sin)->sin_len = sizeof(struct sockaddr_in); \
-      (sin)->sin_family = AF_INET; \
-      (sin)->sin_port = lwip_htons((port)); \
-      inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \
-      memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
-#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
-    inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
-    (port) = lwip_ntohs((sin)->sin_port); }while(0)
-#endif /* LWIP_IPV4 */
-
-#if LWIP_IPV6
-#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
-      (sin6)->sin6_len = sizeof(struct sockaddr_in6); \
-      (sin6)->sin6_family = AF_INET6; \
-      (sin6)->sin6_port = lwip_htons((port)); \
-      (sin6)->sin6_flowinfo = 0; \
-      inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
-      (sin6)->sin6_scope_id = 0; }while(0)
-#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
-    inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
-    (port) = lwip_ntohs((sin6)->sin6_port); }while(0)
-#endif /* LWIP_IPV6 */
-
-#if LWIP_IPV4 && LWIP_IPV6
-static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port);
-
-#define IS_SOCK_ADDR_LEN_VALID(namelen)  (((namelen) == sizeof(struct sockaddr_in)) || \
-                                         ((namelen) == sizeof(struct sockaddr_in6)))
-#define IS_SOCK_ADDR_TYPE_VALID(name)    (((name)->sa_family == AF_INET) || \
-                                         ((name)->sa_family == AF_INET6))
-#define SOCK_ADDR_TYPE_MATCH(name, sock) \
-       ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
-       (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
-#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
-    if (IP_IS_V6(ipaddr)) { \
-      IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
-    } else { \
-      IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
-    } } while(0)
-#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port))
-#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
-  (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
-#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
-#define IS_SOCK_ADDR_LEN_VALID(namelen)  ((namelen) == sizeof(struct sockaddr_in6))
-#define IS_SOCK_ADDR_TYPE_VALID(name)    ((name)->sa_family == AF_INET6)
-#define SOCK_ADDR_TYPE_MATCH(name, sock) 1
-#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
-        IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port)
-#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
-        SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port)
-#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
-#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */
-#define IS_SOCK_ADDR_LEN_VALID(namelen)  ((namelen) == sizeof(struct sockaddr_in))
-#define IS_SOCK_ADDR_TYPE_VALID(name)    ((name)->sa_family == AF_INET)
-#define SOCK_ADDR_TYPE_MATCH(name, sock) 1
-#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
-        IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port)
-#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
-        SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
-#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
-#endif /* LWIP_IPV6 */
-
-#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name)    (((name)->sa_family == AF_UNSPEC) || \
-                                                    IS_SOCK_ADDR_TYPE_VALID(name))
-#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
-                                                    SOCK_ADDR_TYPE_MATCH(name, sock))
-#define IS_SOCK_ADDR_ALIGNED(name)      ((((mem_ptr_t)(name)) % 4) == 0)
-
-
-#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0)
-#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \
-  LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
-  if ((sock)->conn == NULL) { return EINVAL; } }while(0)
-#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \
-  LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
-  if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0)
-#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \
-  LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \
-  if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0)
-
-
-#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name)     API_VAR_REF(name)
-#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name)
-#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name)    API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name)
-#if LWIP_MPU_COMPATIBLE
-#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \
-  name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \
-  if (name == NULL) { \
-    sock_set_errno(sock, ENOMEM); \
-    return -1; \
-  } }while(0)
-#else /* LWIP_MPU_COMPATIBLE */
-#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock)
-#endif /* LWIP_MPU_COMPATIBLE */
-
-#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
-#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int
-#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val))
-#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval)   ((s32_t)*(const int*)(optval))
-#else
-#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval
-#define LWIP_SO_SNDRCVTIMEO_SET(optval, val)  do { \
-  s32_t loc = (val); \
-  ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \
-  ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0)
-#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U))
-#endif
-
-#define NUM_SOCKETS MEMP_NUM_NETCONN
-
-/** This is overridable for the rare case where more than 255 threads
- * select on the same socket...
- */
-#ifndef SELWAIT_T
-#define SELWAIT_T u8_t
-#endif
-
-/** Contains all internal pointers and states used for a socket */
-struct lwip_sock {
-  /** sockets currently are built on netconns, each socket has one netconn */
-  struct netconn *conn;
-  /** data that was left from the previous read */
-  void *lastdata;
-  /** offset in the data that was left from the previous read */
-  u16_t lastoffset;
-  /** number of times data was received, set by event_callback(),
-      tested by the receive and select functions */
-  s16_t rcvevent;
-  /** number of times data was ACKed (free send buffer), set by event_callback(),
-      tested by select */
-  u16_t sendevent;
-  /** error happened for this socket, set by event_callback(), tested by select */
-  u16_t errevent;
-  /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */
-  u8_t err;
-  /** counter of how many threads are waiting for this socket using select */
-  SELWAIT_T select_waiting;
-};
-
-#if LWIP_NETCONN_SEM_PER_THREAD
-#define SELECT_SEM_T        sys_sem_t*
-#define SELECT_SEM_PTR(sem) (sem)
-#else /* LWIP_NETCONN_SEM_PER_THREAD */
-#define SELECT_SEM_T        sys_sem_t
-#define SELECT_SEM_PTR(sem) (&(sem))
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-/** Description for a task waiting in select */
-struct lwip_select_cb {
-  /** Pointer to the next waiting task */
-  struct lwip_select_cb *next;
-  /** Pointer to the previous waiting task */
-  struct lwip_select_cb *prev;
-  /** readset passed to select */
-  fd_set *readset;
-  /** writeset passed to select */
-  fd_set *writeset;
-  /** unimplemented: exceptset passed to select */
-  fd_set *exceptset;
-  /** don't signal the same semaphore twice: set to 1 when signalled */
-  int sem_signalled;
-  /** semaphore to wake up a task waiting for select */
-  SELECT_SEM_T sem;
-};
-
-/** A struct sockaddr replacement that has the same alignment as sockaddr_in/
- *  sockaddr_in6 if instantiated.
- */
-union sockaddr_aligned {
-   struct sockaddr sa;
-#if LWIP_IPV6
-   struct sockaddr_in6 sin6;
-#endif /* LWIP_IPV6 */
-#if LWIP_IPV4
-   struct sockaddr_in sin;
-#endif /* LWIP_IPV4 */
-};
-
-#if LWIP_IGMP
-/* Define the number of IPv4 multicast memberships, default is one per socket */
-#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
-#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
-#endif
-
-/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
-   a socket is closed */
-struct lwip_socket_multicast_pair {
-  /** the socket */
-  struct lwip_sock* sock;
-  /** the interface address */
-  ip4_addr_t if_addr;
-  /** the group address */
-  ip4_addr_t multi_addr;
-};
-
-struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
-
-static int  lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
-static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
-static void lwip_socket_drop_registered_memberships(int s);
-#endif /* LWIP_IGMP */
-
-/** The global array of available sockets */
-static struct lwip_sock sockets[NUM_SOCKETS];
-/** The global list of tasks waiting for select */
-static struct lwip_select_cb *select_cb_list;
-/** This counter is increased from lwip_select when the list is changed
-    and checked in event_callback to see if it has changed. */
-static volatile int select_cb_ctr;
-
-#if LWIP_SOCKET_SET_ERRNO
-#ifndef set_errno
-#define set_errno(err) do { if (err) { errno = (err); } } while(0)
-#endif
-#else /* LWIP_SOCKET_SET_ERRNO */
-#define set_errno(err)
-#endif /* LWIP_SOCKET_SET_ERRNO */
-
-#define sock_set_errno(sk, e) do { \
-  const int sockerr = (e); \
-  sk->err = (u8_t)sockerr; \
-  set_errno(sockerr); \
-} while (0)
-
-/* Forward declaration of some functions */
-static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
-#if !LWIP_TCPIP_CORE_LOCKING
-static void lwip_getsockopt_callback(void *arg);
-static void lwip_setsockopt_callback(void *arg);
-#endif
-static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen);
-static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen);
-
-#if LWIP_IPV4 && LWIP_IPV6
-static void
-sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port)
-{
-  if ((sockaddr->sa_family) == AF_INET6) {
-    SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port);
-    ipaddr->type = IPADDR_TYPE_V6;
-  } else {
-    SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port);
-    ipaddr->type = IPADDR_TYPE_V4;
-  }
-}
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */
-void
-lwip_socket_thread_init(void)
-{
-   netconn_thread_init();
-}
-
-/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */
-void
-lwip_socket_thread_cleanup(void)
-{
-   netconn_thread_cleanup();
-}
-
-/**
- * Map a externally used socket index to the internal socket representation.
- *
- * @param s externally used socket index
- * @return struct lwip_sock for the socket or NULL if not found
- */
-static struct lwip_sock *
-get_socket(int s)
-{
-  struct lwip_sock *sock;
-
-  s -= LWIP_SOCKET_OFFSET;
-
-  if ((s < 0) || (s >= NUM_SOCKETS)) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET));
-    set_errno(EBADF);
-    return NULL;
-  }
-
-  sock = &sockets[s];
-
-  if (!sock->conn) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET));
-    set_errno(EBADF);
-    return NULL;
-  }
-
-  return sock;
-}
-
-/**
- * Same as get_socket but doesn't set errno
- *
- * @param s externally used socket index
- * @return struct lwip_sock for the socket or NULL if not found
- */
-static struct lwip_sock *
-tryget_socket(int s)
-{
-  s -= LWIP_SOCKET_OFFSET;
-  if ((s < 0) || (s >= NUM_SOCKETS)) {
-    return NULL;
-  }
-  if (!sockets[s].conn) {
-    return NULL;
-  }
-  return &sockets[s];
-}
-
-/**
- * Same as tryget_socket but a global routine.
- *
- * @param s externally used socket index
- * @return struct lwip_sock for the socket or NULL if not found
- */
-struct lwip_sock *
-lwip_tryget_socket(int s)
-{
-	return tryget_socket(s);
-}
-
-/**
- * Allocate a new socket for a given netconn.
- *
- * @param newconn the netconn for which to allocate a socket
- * @param accepted 1 if socket has been created by accept(),
- *                 0 if socket has been created by socket()
- * @return the index of the new socket; -1 on error
- */
-static int
-alloc_socket(struct netconn *newconn, int accepted)
-{
-  int i;
-  SYS_ARCH_DECL_PROTECT(lev);
-
-  /* allocate a new socket identifier */
-  for (i = 0; i < NUM_SOCKETS; ++i) {
-    /* Protect socket array */
-    SYS_ARCH_PROTECT(lev);
-    if (!sockets[i].conn) {
-      sockets[i].conn       = newconn;
-      /* The socket is not yet known to anyone, so no need to protect
-         after having marked it as used. */
-      SYS_ARCH_UNPROTECT(lev);
-      sockets[i].lastdata   = NULL;
-      sockets[i].lastoffset = 0;
-      sockets[i].rcvevent   = 0;
-      /* TCP sendbuf is empty, but the socket is not yet writable until connected
-       * (unless it has been created by accept()). */
-      sockets[i].sendevent  = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
-      sockets[i].errevent   = 0;
-      sockets[i].err        = 0;
-      sockets[i].select_waiting = 0;
-      return i + LWIP_SOCKET_OFFSET;
-    }
-    SYS_ARCH_UNPROTECT(lev);
-  }
-  return -1;
-}
-
-/** Free a socket. The socket's netconn must have been
- * delete before!
- *
- * @param sock the socket to free
- * @param is_tcp != 0 for TCP sockets, used to free lastdata
- */
-static void
-free_socket(struct lwip_sock *sock, int is_tcp)
-{
-  void *lastdata;
-
-  lastdata         = sock->lastdata;
-  sock->lastdata   = NULL;
-  sock->lastoffset = 0;
-  sock->err        = 0;
-
-  /* Protect socket array */
-  SYS_ARCH_SET(sock->conn, NULL);
-  /* don't use 'sock' after this line, as another task might have allocated it */
-
-  if (lastdata != NULL) {
-    if (is_tcp) {
-      pbuf_free((struct pbuf *)lastdata);
-    } else {
-      netbuf_delete((struct netbuf *)lastdata);
-    }
-  }
-}
-
-/* Below this, the well-known socket functions are implemented.
- * Use google.com or opengroup.org to get a good description :-)
- *
- * Exceptions are documented!
- */
-
-int
-lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
-  struct lwip_sock *sock, *nsock;
-  struct netconn *newconn;
-  ip_addr_t naddr;
-  u16_t port = 0;
-  int newsock;
-  err_t err;
-  SYS_ARCH_DECL_PROTECT(lev);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
-    sock_set_errno(sock, EWOULDBLOCK);
-    return -1;
-  }
-
-  /* wait for a new connection */
-  err = netconn_accept(sock->conn, &newconn);
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-      sock_set_errno(sock, EOPNOTSUPP);
-    } else if (err == ERR_CLSD) {
-      sock_set_errno(sock, EINVAL);
-    } else {
-      sock_set_errno(sock, err_to_errno(err));
-    }
-    return -1;
-  }
-  LWIP_ASSERT("newconn != NULL", newconn != NULL);
-
-  newsock = alloc_socket(newconn, 1);
-  if (newsock == -1) {
-    netconn_delete(newconn);
-    sock_set_errno(sock, ENFILE);
-    return -1;
-  }
-  LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
-  LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
-  nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
-
-  /* See event_callback: If data comes in right away after an accept, even
-   * though the server task might not have created a new socket yet.
-   * In that case, newconn->socket is counted down (newconn->socket--),
-   * so nsock->rcvevent is >= 1 here!
-   */
-  SYS_ARCH_PROTECT(lev);
-  nsock->rcvevent += (s16_t)(-1 - newconn->socket);
-  newconn->socket = newsock;
-  SYS_ARCH_UNPROTECT(lev);
-
-  /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
-   * not be NULL if addr is valid.
-   */
-  if (addr != NULL) {
-    union sockaddr_aligned tempaddr;
-    /* get the IP address and port of the remote host */
-    err = netconn_peer(newconn, &naddr, &port);
-    if (err != ERR_OK) {
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
-      netconn_delete(newconn);
-      free_socket(nsock, 1);
-      sock_set_errno(sock, err_to_errno(err));
-      return -1;
-    }
-    LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
-
-    IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
-    if (*addrlen > tempaddr.sa.sa_len) {
-      *addrlen = tempaddr.sa.sa_len;
-    }
-    MEMCPY(addr, &tempaddr, *addrlen);
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
-    ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
-    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
-  } else {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock));
-  }
-
-  sock_set_errno(sock, 0);
-  return newsock;
-}
-
-int
-lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
-{
-  struct lwip_sock *sock;
-  ip_addr_t local_addr;
-  u16_t local_port;
-  err_t err;
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
-    /* sockaddr does not match socket type (IPv4/IPv6) */
-    sock_set_errno(sock, err_to_errno(ERR_VAL));
-    return -1;
-  }
-
-  /* check size, family and alignment of 'name' */
-  LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
-             IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
-             sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-  LWIP_UNUSED_ARG(namelen);
-
-  SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port);
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
-  ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
-
-  err = netconn_bind(sock->conn, &local_addr, local_port);
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_close(int s)
-{
-  struct lwip_sock *sock;
-  int is_tcp = 0;
-  err_t err;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (sock->conn != NULL) {
-    is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
-  } else {
-    LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
-  }
-
-#if LWIP_IGMP
-  /* drop all possibly joined IGMP memberships */
-  lwip_socket_drop_registered_memberships(s);
-#endif /* LWIP_IGMP */
-
-  err = netconn_delete(sock->conn);
-  if (err != ERR_OK) {
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  free_socket(sock, is_tcp);
-  set_errno(0);
-  return 0;
-}
-
-int
-lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
-{
-  struct lwip_sock *sock;
-  err_t err;
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
-    /* sockaddr does not match socket type (IPv4/IPv6) */
-    sock_set_errno(sock, err_to_errno(ERR_VAL));
-    return -1;
-  }
-
-  LWIP_UNUSED_ARG(namelen);
-  if (name->sa_family == AF_UNSPEC) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
-    err = netconn_disconnect(sock->conn);
-  } else {
-    ip_addr_t remote_addr;
-    u16_t remote_port;
-
-    /* check size, family and alignment of 'name' */
-    LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
-               IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
-               sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
-    SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
-    ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
-    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
-
-    err = netconn_connect(sock->conn, &remote_addr, remote_port);
-  }
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-/**
- * Set a socket into listen mode.
- * The socket may not have been used for another connection previously.
- *
- * @param s the socket to set to listening mode
- * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
- * @return 0 on success, non-zero on failure
- */
-int
-lwip_listen(int s, int backlog)
-{
-  struct lwip_sock *sock;
-  err_t err;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  /* limit the "backlog" parameter to fit in an u8_t */
-  backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
-
-  err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-      sock_set_errno(sock, EOPNOTSUPP);
-      return -1;
-    }
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_recvfrom(int s, void *mem, size_t len, int flags,
-              struct sockaddr *from, socklen_t *fromlen)
-{
-  struct lwip_sock *sock;
-  void             *buf = NULL;
-  struct pbuf      *p;
-  u16_t            buflen, copylen;
-  int              off = 0;
-  u8_t             done = 0;
-  err_t            err;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  do {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
-    /* Check if there is data left from the last recv operation. */
-    if (sock->lastdata) {
-      buf = sock->lastdata;
-    } else {
-      /* If this is non-blocking call, then check first */
-      if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
-          (sock->rcvevent <= 0)) {
-        if (off > 0) {
-          /* already received data, return that */
-          sock_set_errno(sock, 0);
-          return off;
-        }
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
-        sock_set_errno(sock, EWOULDBLOCK);
-        return -1;
-      }
-
-      /* No data was left from the previous operation, so we try to get
-         some from the network. */
-      if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-        err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
-      } else {
-        err = netconn_recv(sock->conn, (struct netbuf **)&buf);
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
-        err, buf));
-
-      if (err != ERR_OK) {
-        if (off > 0) {
-          if (err == ERR_CLSD) {
-            /* closed but already received data, ensure select gets the FIN, too */
-            event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
-          }
-          /* already received data, return that */
-          sock_set_errno(sock, 0);
-          return off;
-        }
-        /* We should really do some error checking here. */
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
-          s, lwip_strerr(err)));
-        sock_set_errno(sock, err_to_errno(err));
-        if (err == ERR_CLSD) {
-          return 0;
-        } else {
-          return -1;
-        }
-      }
-      LWIP_ASSERT("buf != NULL", buf != NULL);
-      sock->lastdata = buf;
-    }
-
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-      p = (struct pbuf *)buf;
-    } else {
-      p = ((struct netbuf *)buf)->p;
-    }
-    buflen = p->tot_len;
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
-      buflen, len, off, sock->lastoffset));
-
-    buflen -= sock->lastoffset;
-
-    if (len > buflen) {
-      copylen = buflen;
-    } else {
-      copylen = (u16_t)len;
-    }
-
-    /* copy the contents of the received buffer into
-    the supplied memory pointer mem */
-    pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
-
-    off += copylen;
-
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-      LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
-      len -= copylen;
-      if ((len <= 0) ||
-          (p->flags & PBUF_FLAG_PUSH) ||
-          (sock->rcvevent <= 0) ||
-          ((flags & MSG_PEEK) != 0)) {
-        done = 1;
-      }
-    } else {
-      done = 1;
-    }
-
-    /* Check to see from where the data was.*/
-    if (done) {
-#if !SOCKETS_DEBUG
-      if (from && fromlen)
-#endif /* !SOCKETS_DEBUG */
-      {
-        u16_t port;
-        ip_addr_t tmpaddr;
-        ip_addr_t *fromaddr;
-        union sockaddr_aligned saddr;
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
-        if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-          fromaddr = &tmpaddr;
-          netconn_getaddr(sock->conn, fromaddr, &port, 0);
-        } else {
-          port = netbuf_fromport((struct netbuf *)buf);
-          fromaddr = netbuf_fromaddr((struct netbuf *)buf);
-        }
-        IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
-        ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
-        LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
-#if SOCKETS_DEBUG
-        if (from && fromlen)
-#endif /* SOCKETS_DEBUG */
-        {
-          if (*fromlen > saddr.sa.sa_len) {
-            *fromlen = saddr.sa.sa_len;
-          }
-          MEMCPY(from, &saddr, *fromlen);
-        }
-      }
-    }
-
-    /* If we don't peek the incoming message... */
-    if ((flags & MSG_PEEK) == 0) {
-      /* If this is a TCP socket, check if there is data left in the
-         buffer. If so, it should be saved in the sock structure for next
-         time around. */
-      if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
-        sock->lastdata = buf;
-        sock->lastoffset += copylen;
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
-      } else {
-        sock->lastdata = NULL;
-        sock->lastoffset = 0;
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
-        if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-          pbuf_free((struct pbuf *)buf);
-        } else {
-          netbuf_delete((struct netbuf *)buf);
-        }
-        buf = NULL;
-      }
-    }
-  } while (!done);
-
-  sock_set_errno(sock, 0);
-  return off;
-}
-
-int
-lwip_read(int s, void *mem, size_t len)
-{
-  return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
-}
-
-int
-lwip_recv(int s, void *mem, size_t len, int flags)
-{
-  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
-}
-
-int
-lwip_send(int s, const void *data, size_t size, int flags)
-{
-  struct lwip_sock *sock;
-  err_t err;
-  u8_t write_flags;
-  size_t written;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
-                              s, data, size, flags));
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-#if (LWIP_UDP || LWIP_RAW)
-    return lwip_sendto(s, data, size, flags, NULL, 0);
-#else /* (LWIP_UDP || LWIP_RAW) */
-    sock_set_errno(sock, err_to_errno(ERR_ARG));
-    return -1;
-#endif /* (LWIP_UDP || LWIP_RAW) */
-  }
-
-  write_flags = NETCONN_COPY |
-    ((flags & MSG_MORE)     ? NETCONN_MORE      : 0) |
-    ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
-  written = 0;
-  err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written));
-  sock_set_errno(sock, err_to_errno(err));
-  return (err == ERR_OK ? (int)written : -1);
-}
-
-int
-lwip_sendmsg(int s, const struct msghdr *msg, int flags)
-{
-  struct lwip_sock *sock;
-  int i;
-#if LWIP_TCP
-  u8_t write_flags;
-  size_t written;
-#endif
-  int size = 0;
-  err_t err = ERR_OK;
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL,
-             sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
-  LWIP_UNUSED_ARG(msg->msg_control);
-  LWIP_UNUSED_ARG(msg->msg_controllen);
-  LWIP_UNUSED_ARG(msg->msg_flags);
-  LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0),
-             sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
-  if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-#if LWIP_TCP
-    write_flags = NETCONN_COPY |
-    ((flags & MSG_MORE)     ? NETCONN_MORE      : 0) |
-    ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
-
-    for (i = 0; i < msg->msg_iovlen; i++) {
-      written = 0;
-      err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
-      if (err == ERR_OK) {
-        size += written;
-        /* check that the entire IO vector was accepected, if not return a partial write */
-        if (written != msg->msg_iov[i].iov_len)
-          break;
-      }
-      /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */
-      else if (err == ERR_WOULDBLOCK && size > 0) {
-        err = ERR_OK;
-        /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */
-        break;
-      } else {
-        size = -1;
-        break;
-      }
-    }
-    sock_set_errno(sock, err_to_errno(err));
-    return size;
-#else /* LWIP_TCP */
-    sock_set_errno(sock, err_to_errno(ERR_ARG));
-    return -1;
-#endif /* LWIP_TCP */
-  }
-  /* else, UDP and RAW NETCONNs */
-#if LWIP_UDP || LWIP_RAW
-  {
-    struct netbuf *chain_buf;
-
-    LWIP_UNUSED_ARG(flags);
-    LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
-               IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
-               sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
-    /* initialize chain buffer with destination */
-    chain_buf = netbuf_new();
-    if (!chain_buf) {
-      sock_set_errno(sock, err_to_errno(ERR_MEM));
-      return -1;
-    }
-    if (msg->msg_name) {
-      u16_t remote_port;
-      SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
-      netbuf_fromport(chain_buf) = remote_port;
-    }
-#if LWIP_NETIF_TX_SINGLE_PBUF
-    for (i = 0; i < msg->msg_iovlen; i++) {
-      size += msg->msg_iov[i].iov_len;
-    }
-    /* Allocate a new netbuf and copy the data into it. */
-    if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
-       err = ERR_MEM;
-    } else {
-      /* flatten the IO vectors */
-      size_t offset = 0;
-      for (i = 0; i < msg->msg_iovlen; i++) {
-        MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
-        offset += msg->msg_iov[i].iov_len;
-      }
-#if LWIP_CHECKSUM_ON_COPY
-      {
-        /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */
-        u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
-        netbuf_set_chksum(chain_buf, chksum);
-      }
-#endif /* LWIP_CHECKSUM_ON_COPY */
-      err = ERR_OK;
-    }
-#else /* LWIP_NETIF_TX_SINGLE_PBUF */
-    /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain
-       manually to avoid having to allocate, chain, and delete a netbuf for each iov */
-    for (i = 0; i < msg->msg_iovlen; i++) {
-      struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
-      if (p == NULL) {
-        err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */
-        break;
-      }
-      p->payload = msg->msg_iov[i].iov_base;
-      LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
-      p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
-      /* netbuf empty, add new pbuf */
-      if (chain_buf->p == NULL) {
-        chain_buf->p = chain_buf->ptr = p;
-        /* add pbuf to existing pbuf chain */
-      } else {
-        pbuf_cat(chain_buf->p, p);
-      }
-    }
-    /* save size of total chain */
-    if (err == ERR_OK) {
-      size = netbuf_len(chain_buf);
-    }
-#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
-
-    if (err == ERR_OK) {
-      /* send the data */
-      err = netconn_send(sock->conn, chain_buf);
-    }
-
-    /* deallocated the buffer */
-    netbuf_delete(chain_buf);
-
-    sock_set_errno(sock, err_to_errno(err));
-    return (err == ERR_OK ? size : -1);
-  }
-#else /* LWIP_UDP || LWIP_RAW */
-  sock_set_errno(sock, err_to_errno(ERR_ARG));
-  return -1;
-#endif /* LWIP_UDP || LWIP_RAW */
-}
-
-int
-lwip_sendto(int s, const void *data, size_t size, int flags,
-       const struct sockaddr *to, socklen_t tolen)
-{
-  struct lwip_sock *sock;
-  err_t err;
-  u16_t short_size;
-  u16_t remote_port;
-  struct netbuf buf;
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
-#if LWIP_TCP
-    return lwip_send(s, data, size, flags);
-#else /* LWIP_TCP */
-    LWIP_UNUSED_ARG(flags);
-    sock_set_errno(sock, err_to_errno(ERR_ARG));
-    return -1;
-#endif /* LWIP_TCP */
-  }
-
-  if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
-    /* sockaddr does not match socket type (IPv4/IPv6) */
-    sock_set_errno(sock, err_to_errno(ERR_VAL));
-    return -1;
-  }
-
-  /* @todo: split into multiple sendto's? */
-  LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
-  short_size = (u16_t)size;
-  LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
-             (IS_SOCK_ADDR_LEN_VALID(tolen) &&
-             IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
-             sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-  LWIP_UNUSED_ARG(tolen);
-
-  /* initialize a buffer */
-  buf.p = buf.ptr = NULL;
-#if LWIP_CHECKSUM_ON_COPY
-  buf.flags = 0;
-#endif /* LWIP_CHECKSUM_ON_COPY */
-  if (to) {
-    SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
-  } else {
-    remote_port = 0;
-    ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
-  }
-  netbuf_fromport(&buf) = remote_port;
-
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
-              s, data, short_size, flags));
-  ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
-
-  /* make the buffer point to the data that should be sent */
-#if LWIP_NETIF_TX_SINGLE_PBUF
-  /* Allocate a new netbuf and copy the data into it. */
-  if (netbuf_alloc(&buf, short_size) == NULL) {
-    err = ERR_MEM;
-  } else {
-#if LWIP_CHECKSUM_ON_COPY
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
-      u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
-      netbuf_set_chksum(&buf, chksum);
-    } else
-#endif /* LWIP_CHECKSUM_ON_COPY */
-    {
-      MEMCPY(buf.p->payload, data, short_size);
-    }
-    err = ERR_OK;
-  }
-#else /* LWIP_NETIF_TX_SINGLE_PBUF */
-  err = netbuf_ref(&buf, data, short_size);
-#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
-  if (err == ERR_OK) {
-    /* send the data */
-    err = netconn_send(sock->conn, &buf);
-  }
-
-  /* deallocated the buffer */
-  netbuf_free(&buf);
-
-  sock_set_errno(sock, err_to_errno(err));
-  return (err == ERR_OK ? short_size : -1);
-}
-
-int
-lwip_socket(int domain, int type, int protocol)
-{
-  struct netconn *conn;
-  int i;
-
-#if !LWIP_IPV6
-  LWIP_UNUSED_ARG(domain); /* @todo: check this */
-#endif /* LWIP_IPV6 */
-
-  /* create a netconn */
-  switch (type) {
-  case SOCK_RAW:
-    conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
-                                               (u8_t)protocol, event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
-                                 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  case SOCK_DGRAM:
-    conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
-                 ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
-                 event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
-                                 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  case SOCK_STREAM:
-    conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
-                                 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
-                                 domain, type, protocol));
-    set_errno(EINVAL);
-    return -1;
-  }
-
-  if (!conn) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
-    set_errno(ENOBUFS);
-    return -1;
-  }
-
-  i = alloc_socket(conn, 0);
-
-  if (i == -1) {
-    netconn_delete(conn);
-    set_errno(ENFILE);
-    return -1;
-  }
-  conn->socket = i;
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
-  set_errno(0);
-  return i;
-}
-
-int
-lwip_write(int s, const void *data, size_t size)
-{
-  return lwip_send(s, data, size, 0);
-}
-
-int
-lwip_writev(int s, const struct iovec *iov, int iovcnt)
-{
-  struct msghdr msg;
-
-  msg.msg_name = NULL;
-  msg.msg_namelen = 0;
-  /* Hack: we have to cast via number to cast from 'const' pointer to non-const.
-     Blame the opengroup standard for this inconsistency. */
-  msg.msg_iov = (struct iovec *)(size_t)iov;
-  msg.msg_iovlen = iovcnt;
-  msg.msg_control = NULL;
-  msg.msg_controllen = 0;
-  msg.msg_flags = 0;
-  return lwip_sendmsg(s, &msg, 0);
-}
-
-/**
- * Go through the readset and writeset lists and see which socket of the sockets
- * set in the sets has events. On return, readset, writeset and exceptset have
- * the sockets enabled that had events.
- *
- * @param maxfdp1 the highest socket index in the sets
- * @param readset_in    set of sockets to check for read events
- * @param writeset_in   set of sockets to check for write events
- * @param exceptset_in  set of sockets to check for error events
- * @param readset_out   set of sockets that had read events
- * @param writeset_out  set of sockets that had write events
- * @param exceptset_out set os sockets that had error events
- * @return number of sockets that had events (read/write/exception) (>= 0)
- */
-static int
-lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
-             fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
-{
-  int i, nready = 0;
-  fd_set lreadset, lwriteset, lexceptset;
-  struct lwip_sock *sock;
-  SYS_ARCH_DECL_PROTECT(lev);
-
-  FD_ZERO(&lreadset);
-  FD_ZERO(&lwriteset);
-  FD_ZERO(&lexceptset);
-
-  /* Go through each socket in each list to count number of sockets which
-     currently match */
-  for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
-    /* if this FD is not in the set, continue */
-    if (!(readset_in && FD_ISSET(i, readset_in)) &&
-        !(writeset_in && FD_ISSET(i, writeset_in)) &&
-        !(exceptset_in && FD_ISSET(i, exceptset_in))) {
-      continue;
-    }
-    /* First get the socket's status (protected)... */
-    SYS_ARCH_PROTECT(lev);
-    sock = tryget_socket(i);
-    if (sock != NULL) {
-      void* lastdata = sock->lastdata;
-      s16_t rcvevent = sock->rcvevent;
-      u16_t sendevent = sock->sendevent;
-      u16_t errevent = sock->errevent;
-      SYS_ARCH_UNPROTECT(lev);
-
-      /* ... then examine it: */
-      /* See if netconn of this socket is ready for read */
-      if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
-        FD_SET(i, &lreadset);
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
-        nready++;
-      }
-      /* See if netconn of this socket is ready for write */
-      if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
-        FD_SET(i, &lwriteset);
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
-        nready++;
-      }
-      /* See if netconn of this socket had an error */
-      if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
-        FD_SET(i, &lexceptset);
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
-        nready++;
-      }
-    } else {
-      SYS_ARCH_UNPROTECT(lev);
-      /* continue on to next FD in list */
-    }
-  }
-  /* copy local sets to the ones provided as arguments */
-  *readset_out = lreadset;
-  *writeset_out = lwriteset;
-  *exceptset_out = lexceptset;
-
-  LWIP_ASSERT("nready >= 0", nready >= 0);
-  return nready;
-}
-
-int
-lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
-            struct timeval *timeout)
-{
-  u32_t waitres = 0;
-  int nready;
-  fd_set lreadset, lwriteset, lexceptset;
-  u32_t msectimeout;
-  struct lwip_select_cb select_cb;
-  int i;
-  int maxfdp2;
-#if LWIP_NETCONN_SEM_PER_THREAD
-  int waited = 0;
-#endif
-  SYS_ARCH_DECL_PROTECT(lev);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
-                  maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
-                  timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
-                  timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
-
-  /* Go through each socket in each list to count number of sockets which
-     currently match */
-  nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
-
-  /* If we don't have any current events, then suspend if we are supposed to */
-  if (!nready) {
-    if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
-      /* This is OK as the local fdsets are empty and nready is zero,
-         or we would have returned earlier. */
-      goto return_copy_fdsets;
-    }
-
-    /* None ready: add our semaphore to list:
-       We don't actually need any dynamic memory. Our entry on the
-       list is only valid while we are in this function, so it's ok
-       to use local variables. */
-
-    select_cb.next = NULL;
-    select_cb.prev = NULL;
-    select_cb.readset = readset;
-    select_cb.writeset = writeset;
-    select_cb.exceptset = exceptset;
-    select_cb.sem_signalled = 0;
-#if LWIP_NETCONN_SEM_PER_THREAD
-    select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
-#else /* LWIP_NETCONN_SEM_PER_THREAD */
-    if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) {
-      /* failed to create semaphore */
-      set_errno(ENOMEM);
-      return -1;
-    }
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-    /* Protect the select_cb_list */
-    SYS_ARCH_PROTECT(lev);
-
-    /* Put this select_cb on top of list */
-    select_cb.next = select_cb_list;
-    if (select_cb_list != NULL) {
-      select_cb_list->prev = &select_cb;
-    }
-    select_cb_list = &select_cb;
-    /* Increasing this counter tells event_callback that the list has changed. */
-    select_cb_ctr++;
-
-    /* Now we can safely unprotect */
-    SYS_ARCH_UNPROTECT(lev);
-
-    /* Increase select_waiting for each socket we are interested in */
-    maxfdp2 = maxfdp1;
-    for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
-      if ((readset && FD_ISSET(i, readset)) ||
-          (writeset && FD_ISSET(i, writeset)) ||
-          (exceptset && FD_ISSET(i, exceptset))) {
-        struct lwip_sock *sock;
-        SYS_ARCH_PROTECT(lev);
-        sock = tryget_socket(i);
-        if (sock != NULL) {
-          sock->select_waiting++;
-          LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
-        } else {
-          /* Not a valid socket */
-          nready = -1;
-          maxfdp2 = i;
-          SYS_ARCH_UNPROTECT(lev);
-          break;
-        }
-        SYS_ARCH_UNPROTECT(lev);
-      }
-    }
-
-    if (nready >= 0) {
-      /* Call lwip_selscan again: there could have been events between
-         the last scan (without us on the list) and putting us on the list! */
-      nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
-      if (!nready) {
-        /* Still none ready, just wait to be woken */
-        if (timeout == 0) {
-          /* Wait forever */
-          msectimeout = 0;
-        } else {
-          msectimeout =  ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
-          if (msectimeout == 0) {
-            /* Wait 1ms at least (0 means wait forever) */
-            msectimeout = 1;
-          }
-        }
-
-        waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout);
-#if LWIP_NETCONN_SEM_PER_THREAD
-        waited = 1;
-#endif
-      }
-    }
-
-    /* Decrease select_waiting for each socket we are interested in */
-    for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) {
-      if ((readset && FD_ISSET(i, readset)) ||
-          (writeset && FD_ISSET(i, writeset)) ||
-          (exceptset && FD_ISSET(i, exceptset))) {
-        struct lwip_sock *sock;
-        SYS_ARCH_PROTECT(lev);
-        sock = tryget_socket(i);
-        if (sock != NULL) {
-          /* @todo: what if this is a new socket (reallocated?) in this case,
-             select_waiting-- would be wrong (a global 'sockalloc' counter,
-             stored per socket could help) */
-          LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
-          if (sock->select_waiting > 0) {
-            sock->select_waiting--;
-          }
-        } else {
-          /* Not a valid socket */
-          nready = -1;
-        }
-        SYS_ARCH_UNPROTECT(lev);
-      }
-    }
-    /* Take us off the list */
-    SYS_ARCH_PROTECT(lev);
-    if (select_cb.next != NULL) {
-      select_cb.next->prev = select_cb.prev;
-    }
-    if (select_cb_list == &select_cb) {
-      LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
-      select_cb_list = select_cb.next;
-    } else {
-      LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
-      select_cb.prev->next = select_cb.next;
-    }
-    /* Increasing this counter tells event_callback that the list has changed. */
-    select_cb_ctr++;
-    SYS_ARCH_UNPROTECT(lev);
-
-#if LWIP_NETCONN_SEM_PER_THREAD
-    if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
-      /* don't leave the thread-local semaphore signalled */
-      sys_arch_sem_wait(select_cb.sem, 1);
-    }
-#else /* LWIP_NETCONN_SEM_PER_THREAD */
-    sys_sem_free(&select_cb.sem);
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-    if (nready < 0) {
-      /* This happens when a socket got closed while waiting */
-      set_errno(EBADF);
-      return -1;
-    }
-
-    if (waitres == SYS_ARCH_TIMEOUT) {
-      /* Timeout */
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
-      /* This is OK as the local fdsets are empty and nready is zero,
-         or we would have returned earlier. */
-      goto return_copy_fdsets;
-    }
-
-    /* See what's set */
-    nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
-  }
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
-return_copy_fdsets:
-  set_errno(0);
-  if (readset) {
-    *readset = lreadset;
-  }
-  if (writeset) {
-    *writeset = lwriteset;
-  }
-  if (exceptset) {
-    *exceptset = lexceptset;
-  }
-  return nready;
-}
-
-/**
- * Callback registered in the netconn layer for each socket-netconn.
- * Processes recvevent (data available) and wakes up tasks waiting for select.
- */
-static void
-event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
-{
-  int s;
-  struct lwip_sock *sock;
-  struct lwip_select_cb *scb;
-  int last_select_cb_ctr;
-  SYS_ARCH_DECL_PROTECT(lev);
-
-  LWIP_UNUSED_ARG(len);
-
-  /* Get socket */
-  if (conn) {
-    s = conn->socket;
-    if (s < 0) {
-      /* Data comes in right away after an accept, even though
-       * the server task might not have created a new socket yet.
-       * Just count down (or up) if that's the case and we
-       * will use the data later. Note that only receive events
-       * can happen before the new socket is set up. */
-      SYS_ARCH_PROTECT(lev);
-      if (conn->socket < 0) {
-        if (evt == NETCONN_EVT_RCVPLUS) {
-          conn->socket--;
-        }
-        SYS_ARCH_UNPROTECT(lev);
-        return;
-      }
-      s = conn->socket;
-      SYS_ARCH_UNPROTECT(lev);
-    }
-
-    sock = get_socket(s);
-    if (!sock) {
-      return;
-    }
-  } else {
-    return;
-  }
-
-  SYS_ARCH_PROTECT(lev);
-  /* Set event as required */
-  switch (evt) {
-    case NETCONN_EVT_RCVPLUS:
-      sock->rcvevent++;
-      break;
-    case NETCONN_EVT_RCVMINUS:
-      sock->rcvevent--;
-      break;
-    case NETCONN_EVT_SENDPLUS:
-      sock->sendevent = 1;
-      break;
-    case NETCONN_EVT_SENDMINUS:
-      sock->sendevent = 0;
-      break;
-    case NETCONN_EVT_ERROR:
-      sock->errevent = 1;
-      break;
-    default:
-      LWIP_ASSERT("unknown event", 0);
-      break;
-  }
-
-  if (sock->select_waiting == 0) {
-    /* noone is waiting for this socket, no need to check select_cb_list */
-    SYS_ARCH_UNPROTECT(lev);
-    return;
-  }
-
-  /* Now decide if anyone is waiting for this socket */
-  /* NOTE: This code goes through the select_cb_list list multiple times
-     ONLY IF a select was actually waiting. We go through the list the number
-     of waiting select calls + 1. This list is expected to be small. */
-
-  /* At this point, SYS_ARCH is still protected! */
-again:
-  for (scb = select_cb_list; scb != NULL; scb = scb->next) {
-    /* remember the state of select_cb_list to detect changes */
-    last_select_cb_ctr = select_cb_ctr;
-    if (scb->sem_signalled == 0) {
-      /* semaphore not signalled yet */
-      int do_signal = 0;
-      /* Test this select call for our socket */
-      if (sock->rcvevent > 0) {
-        if (scb->readset && FD_ISSET(s, scb->readset)) {
-          do_signal = 1;
-        }
-      }
-      if (sock->sendevent != 0) {
-        if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
-          do_signal = 1;
-        }
-      }
-      if (sock->errevent != 0) {
-        if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
-          do_signal = 1;
-        }
-      }
-      if (do_signal) {
-        scb->sem_signalled = 1;
-        /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
-           lead to the select thread taking itself off the list, invalidating the semaphore. */
-        sys_sem_signal(SELECT_SEM_PTR(scb->sem));
-      }
-    }
-    /* unlock interrupts with each step */
-    SYS_ARCH_UNPROTECT(lev);
-    /* this makes sure interrupt protection time is short */
-    SYS_ARCH_PROTECT(lev);
-    if (last_select_cb_ctr != select_cb_ctr) {
-      /* someone has changed select_cb_list, restart at the beginning */
-      goto again;
-    }
-  }
-  SYS_ARCH_UNPROTECT(lev);
-}
-
-/**
- * Unimplemented: Close one end of a full-duplex connection.
- * Currently, the full connection is closed.
- */
-int
-lwip_shutdown(int s, int how)
-{
-  struct lwip_sock *sock;
-  err_t err;
-  u8_t shut_rx = 0, shut_tx = 0;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  if (sock->conn != NULL) {
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-      sock_set_errno(sock, EOPNOTSUPP);
-      return -1;
-    }
-  } else {
-    sock_set_errno(sock, ENOTCONN);
-    return -1;
-  }
-
-  if (how == SHUT_RD) {
-    shut_rx = 1;
-  } else if (how == SHUT_WR) {
-    shut_tx = 1;
-  } else if (how == SHUT_RDWR) {
-    shut_rx = 1;
-    shut_tx = 1;
-  } else {
-    sock_set_errno(sock, EINVAL);
-    return -1;
-  }
-  err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
-
-  sock_set_errno(sock, err_to_errno(err));
-  return (err == ERR_OK ? 0 : -1);
-}
-
-static int
-lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
-{
-  struct lwip_sock *sock;
-  union sockaddr_aligned saddr;
-  ip_addr_t naddr;
-  u16_t port;
-  err_t err;
-
-  sock = get_socket(s);
-  if (!sock) {
-    return -1;
-  }
-
-  /* get the IP address and port */
-  /* @todo: this does not work for IPv6, yet */
-  err = netconn_getaddr(sock->conn, &naddr, &port, local);
-  if (err != ERR_OK) {
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-  IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
-  ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port));
-
-  if (*namelen > saddr.sa.sa_len) {
-    *namelen = saddr.sa.sa_len;
-  }
-  MEMCPY(name, &saddr, *namelen);
-
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
-{
-  return lwip_getaddrname(s, name, namelen, 0);
-}
-
-int
-lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
-{
-  return lwip_getaddrname(s, name, namelen, 1);
-}
-
-int
-lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
-{
-  u8_t err;
-  struct lwip_sock *sock = get_socket(s);
-#if !LWIP_TCPIP_CORE_LOCKING
-  LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
-#endif /* !LWIP_TCPIP_CORE_LOCKING */
-
-  if (!sock) {
-    return -1;
-  }
-
-  if ((NULL == optval) || (NULL == optlen)) {
-    sock_set_errno(sock, EFAULT);
-    return -1;
-  }
-
-#if LWIP_TCPIP_CORE_LOCKING
-  /* core-locking can just call the -impl function */
-  LOCK_TCPIP_CORE();
-  err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
-  UNLOCK_TCPIP_CORE();
-
-#else /* LWIP_TCPIP_CORE_LOCKING */
-
-#if LWIP_MPU_COMPATIBLE
-  /* MPU_COMPATIBLE copies the optval data, so check for max size here */
-  if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
-    sock_set_errno(sock, ENOBUFS);
-    return -1;
-  }
-#endif /* LWIP_MPU_COMPATIBLE */
-
-  LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
-#if !LWIP_MPU_COMPATIBLE
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
-#endif /* !LWIP_MPU_COMPATIBLE */
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
-#if LWIP_NETCONN_SEM_PER_THREAD
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
-#else
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
-#endif
-  err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
-  if (err != ERR_OK) {
-    LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-  sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
-
-  /* write back optlen and optval */
-  *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
-#if LWIP_MPU_COMPATIBLE
-  MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
-    LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
-#endif /* LWIP_MPU_COMPATIBLE */
-
-  /* maybe lwip_getsockopt_internal has changed err */
-  err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
-  LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
-  sock_set_errno(sock, err);
-  return err ? -1 : 0;
-}
-
-#if !LWIP_TCPIP_CORE_LOCKING
-/** lwip_getsockopt_callback: only used without CORE_LOCKING
- * to get into the tcpip_thread
- */
-static void
-lwip_getsockopt_callback(void *arg)
-{
-  struct lwip_setgetsockopt_data *data;
-  LWIP_ASSERT("arg != NULL", arg != NULL);
-  data = (struct lwip_setgetsockopt_data*)arg;
-
-  data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
-#if LWIP_MPU_COMPATIBLE
-    data->optval,
-#else /* LWIP_MPU_COMPATIBLE */
-    data->optval.p,
-#endif /* LWIP_MPU_COMPATIBLE */
-    &data->optlen);
-
-  sys_sem_signal((sys_sem_t*)(data->completed_sem));
-}
-#endif  /* LWIP_TCPIP_CORE_LOCKING */
-
-/** lwip_getsockopt_impl: the actual implementation of getsockopt:
- * same argument as lwip_getsockopt, either called directly or through callback
- */
-static u8_t
-lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen)
-{
-  u8_t err = 0;
-  struct lwip_sock *sock = tryget_socket(s);
-  if (!sock) {
-    return EBADF;
-  }
-
-  switch (level) {
-
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-    switch (optname) {
-
-#if LWIP_TCP
-    case SO_ACCEPTCONN:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
-      if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
-        return ENOPROTOOPT;
-      }
-      if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
-        *(int*)optval = 1;
-      } else {
-        *(int*)optval = 0;
-      }
-      break;
-#endif /* LWIP_TCP */
-
-    /* The option flags */
-    case SO_BROADCAST:
-    case SO_KEEPALIVE:
-#if SO_REUSE
-    case SO_REUSEADDR:
-#endif /* SO_REUSE */
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
-      *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
-                                  s, optname, (*(int*)optval?"on":"off")));
-      break;
-
-    case SO_TYPE:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
-      switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
-      case NETCONN_RAW:
-        *(int*)optval = SOCK_RAW;
-        break;
-      case NETCONN_TCP:
-        *(int*)optval = SOCK_STREAM;
-        break;
-      case NETCONN_UDP:
-        *(int*)optval = SOCK_DGRAM;
-        break;
-      default: /* unrecognized socket type */
-        *(int*)optval = netconn_type(sock->conn);
-        LWIP_DEBUGF(SOCKETS_DEBUG,
-                    ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
-                    s, *(int *)optval));
-      }  /* switch (netconn_type(sock->conn)) */
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
-                  s, *(int *)optval));
-      break;
-
-    case SO_ERROR:
-      LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int);
-      /* only overwrite ERR_OK or temporary errors */
-      if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) {
-        sock_set_errno(sock, err_to_errno(sock->conn->last_err));
-      }
-      *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err);
-      sock->err = 0;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
-                  s, *(int *)optval));
-      break;
-
-#if LWIP_SO_SNDTIMEO
-    case SO_SNDTIMEO:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
-      LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
-      break;
-#endif /* LWIP_SO_SNDTIMEO */
-#if LWIP_SO_RCVTIMEO
-    case SO_RCVTIMEO:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
-      LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
-      break;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
-    case SO_RCVBUF:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
-      *(int *)optval = netconn_get_recvbufsize(sock->conn);
-      break;
-#endif /* LWIP_SO_RCVBUF */
-#if LWIP_SO_LINGER
-    case SO_LINGER:
-      {
-        s16_t conn_linger;
-        struct linger* linger = (struct linger*)optval;
-        LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger);
-        conn_linger = sock->conn->linger;
-        if (conn_linger >= 0) {
-          linger->l_onoff = 1;
-          linger->l_linger = (int)conn_linger;
-        } else {
-          linger->l_onoff = 0;
-          linger->l_linger = 0;
-        }
-      }
-      break;
-#endif /* LWIP_SO_LINGER */
-#if LWIP_UDP
-    case SO_NO_CHECK:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP);
-#if LWIP_UDPLITE
-      if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
-        /* this flag is only available for UDP, not for UDP lite */
-        return EAFNOSUPPORT;
-      }
-#endif /* LWIP_UDPLITE */
-      *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
-      break;
-#endif /* LWIP_UDP*/
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-    switch (optname) {
-    case IP_TTL:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
-      *(int*)optval = sock->conn->pcb.ip->ttl;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
-                  s, *(int *)optval));
-      break;
-    case IP_TOS:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
-      *(int*)optval = sock->conn->pcb.ip->tos;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
-                  s, *(int *)optval));
-      break;
-#if LWIP_MULTICAST_TX_OPTIONS
-    case IP_MULTICAST_TTL:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
-      if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
-        return ENOPROTOOPT;
-      }
-      *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
-                  s, *(int *)optval));
-      break;
-    case IP_MULTICAST_IF:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr);
-      if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
-        return ENOPROTOOPT;
-      }
-      inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
-                  s, *(u32_t *)optval));
-      break;
-    case IP_MULTICAST_LOOP:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
-      if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
-        *(u8_t*)optval = 1;
-      } else {
-        *(u8_t*)optval = 0;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
-                  s, *(int *)optval));
-      break;
-#endif /* LWIP_MULTICAST_TX_OPTIONS */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-    /* Special case: all IPPROTO_TCP option take an int */
-    LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
-    switch (optname) {
-    case TCP_NODELAY:
-      *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
-                  s, (*(int*)optval)?"on":"off") );
-      break;
-    case TCP_KEEPALIVE:
-      *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n",
-                  s, *(int *)optval));
-      break;
-
-#if LWIP_TCP_KEEPALIVE
-    case TCP_KEEPIDLE:
-      *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n",
-                  s, *(int *)optval));
-      break;
-    case TCP_KEEPINTVL:
-      *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n",
-                  s, *(int *)optval));
-      break;
-    case TCP_KEEPCNT:
-      *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n",
-                  s, *(int *)optval));
-      break;
-#endif /* LWIP_TCP_KEEPALIVE */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_TCP */
-
-#if LWIP_IPV6
-/* Level: IPPROTO_IPV6 */
-  case IPPROTO_IPV6:
-    switch (optname) {
-    case IPV6_V6ONLY:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
-      /* @todo: this does not work for datagram sockets, yet */
-      if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-        return ENOPROTOOPT;
-      }
-      *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
-                  s, *(int *)optval));
-      break;
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_IPV6 */
-
-#if LWIP_UDP && LWIP_UDPLITE
-  /* Level: IPPROTO_UDPLITE */
-  case IPPROTO_UDPLITE:
-    /* Special case: all IPPROTO_UDPLITE option take an int */
-    LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
-    /* If this is no UDP lite socket, ignore any options. */
-    if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
-      return ENOPROTOOPT;
-    }
-    switch (optname) {
-    case UDPLITE_SEND_CSCOV:
-      *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
-                  s, (*(int*)optval)) );
-      break;
-    case UDPLITE_RECV_CSCOV:
-      *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
-                  s, (*(int*)optval)) );
-      break;
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_UDP */
-  /* Level: IPPROTO_RAW */
-  case IPPROTO_RAW:
-    switch (optname) {
-#if LWIP_IPV6 && LWIP_RAW
-    case IPV6_CHECKSUM:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW);
-      if (sock->conn->pcb.raw->chksum_reqd == 0) {
-        *(int *)optval = -1;
-      } else {
-        *(int *)optval = sock->conn->pcb.raw->chksum_offset;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n",
-                  s, (*(int*)optval)) );
-      break;
-#endif /* LWIP_IPV6 && LWIP_RAW */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
-                                s, level, optname));
-    err = ENOPROTOOPT;
-    break;
-  } /* switch (level) */
-
-  return err;
-}
-
-int
-lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
-{
-  u8_t err = 0;
-  struct lwip_sock *sock = get_socket(s);
-#if !LWIP_TCPIP_CORE_LOCKING
-  LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
-#endif /* !LWIP_TCPIP_CORE_LOCKING */
-
-  if (!sock) {
-    return -1;
-  }
-
-  if (NULL == optval) {
-    sock_set_errno(sock, EFAULT);
-    return -1;
-  }
-
-#if LWIP_TCPIP_CORE_LOCKING
-  /* core-locking can just call the -impl function */
-  LOCK_TCPIP_CORE();
-  err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
-  UNLOCK_TCPIP_CORE();
-
-#else /* LWIP_TCPIP_CORE_LOCKING */
-
-#if LWIP_MPU_COMPATIBLE
-  /* MPU_COMPATIBLE copies the optval data, so check for max size here */
-  if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
-    sock_set_errno(sock, ENOBUFS);
-    return -1;
-  }
-#endif /* LWIP_MPU_COMPATIBLE */
-
-  LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
-#if LWIP_MPU_COMPATIBLE
-  MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
-#else /* LWIP_MPU_COMPATIBLE */
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval;
-#endif /* LWIP_MPU_COMPATIBLE */
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
-#if LWIP_NETCONN_SEM_PER_THREAD
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
-#else
-  LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
-#endif
-  err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
-  if (err != ERR_OK) {
-    LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-  sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
-
-  /* maybe lwip_getsockopt_internal has changed err */
-  err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
-  LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
-#endif  /* LWIP_TCPIP_CORE_LOCKING */
-
-  sock_set_errno(sock, err);
-  return err ? -1 : 0;
-}
-
-#if !LWIP_TCPIP_CORE_LOCKING
-/** lwip_setsockopt_callback: only used without CORE_LOCKING
- * to get into the tcpip_thread
- */
-static void
-lwip_setsockopt_callback(void *arg)
-{
-  struct lwip_setgetsockopt_data *data;
-  LWIP_ASSERT("arg != NULL", arg != NULL);
-  data = (struct lwip_setgetsockopt_data*)arg;
-
-  data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
-#if LWIP_MPU_COMPATIBLE
-    data->optval,
-#else /* LWIP_MPU_COMPATIBLE */
-    data->optval.pc,
-#endif /* LWIP_MPU_COMPATIBLE */
-    data->optlen);
-
-  sys_sem_signal((sys_sem_t*)(data->completed_sem));
-}
-#endif  /* LWIP_TCPIP_CORE_LOCKING */
-
-/** lwip_setsockopt_impl: the actual implementation of setsockopt:
- * same argument as lwip_setsockopt, either called directly or through callback
- */
-static u8_t
-lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen)
-{
-  u8_t err = 0;
-  struct lwip_sock *sock = tryget_socket(s);
-  if (!sock) {
-    return EBADF;
-  }
-
-  switch (level) {
-
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-    switch (optname) {
-
-    /* SO_ACCEPTCONN is get-only */
-
-    /* The option flags */
-    case SO_BROADCAST:
-    case SO_KEEPALIVE:
-#if SO_REUSE
-    case SO_REUSEADDR:
-#endif /* SO_REUSE */
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
-      if (*(const int*)optval) {
-        ip_set_option(sock->conn->pcb.ip, optname);
-      } else {
-        ip_reset_option(sock->conn->pcb.ip, optname);
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
-                  s, optname, (*(const int*)optval?"on":"off")));
-      break;
-
-    /* SO_TYPE is get-only */
-    /* SO_ERROR is get-only */
-
-#if LWIP_SO_SNDTIMEO
-    case SO_SNDTIMEO:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
-      netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
-      break;
-#endif /* LWIP_SO_SNDTIMEO */
-#if LWIP_SO_RCVTIMEO
-    case SO_RCVTIMEO:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
-      netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
-      break;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
-    case SO_RCVBUF:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int);
-      netconn_set_recvbufsize(sock->conn, *(const int*)optval);
-      break;
-#endif /* LWIP_SO_RCVBUF */
-#if LWIP_SO_LINGER
-    case SO_LINGER:
-      {
-        const struct linger* linger = (const struct linger*)optval;
-        LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger);
-        if (linger->l_onoff) {
-          int lingersec = linger->l_linger;
-          if (lingersec < 0) {
-            return EINVAL;
-          }
-          if (lingersec > 0xFFFF) {
-            lingersec = 0xFFFF;
-          }
-          sock->conn->linger = (s16_t)lingersec;
-        } else {
-          sock->conn->linger = -1;
-        }
-      }
-      break;
-#endif /* LWIP_SO_LINGER */
-#if LWIP_UDP
-    case SO_NO_CHECK:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
-#if LWIP_UDPLITE
-      if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
-        /* this flag is only available for UDP, not for UDP lite */
-        return EAFNOSUPPORT;
-      }
-#endif /* LWIP_UDPLITE */
-      if (*(const int*)optval) {
-        udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
-      } else {
-        udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
-      }
-      break;
-#endif /* LWIP_UDP */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-    switch (optname) {
-    case IP_TTL:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
-      sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
-                  s, sock->conn->pcb.ip->ttl));
-      break;
-    case IP_TOS:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
-      sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
-                  s, sock->conn->pcb.ip->tos));
-      break;
-#if LWIP_MULTICAST_TX_OPTIONS
-    case IP_MULTICAST_TTL:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
-      udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval));
-      break;
-    case IP_MULTICAST_IF:
-      {
-        ip4_addr_t if_addr;
-        LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
-        inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval);
-        udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
-      }
-      break;
-    case IP_MULTICAST_LOOP:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
-      if (*(const u8_t*)optval) {
-        udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
-      } else {
-        udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
-      }
-      break;
-#endif /* LWIP_MULTICAST_TX_OPTIONS */
-#if LWIP_IGMP
-    case IP_ADD_MEMBERSHIP:
-    case IP_DROP_MEMBERSHIP:
-      {
-        /* If this is a TCP or a RAW socket, ignore these options. */
-        /* @todo: assign membership to this socket so that it is dropped when closing the socket */
-        err_t igmp_err;
-        const struct ip_mreq *imr = (const struct ip_mreq *)optval;
-        ip4_addr_t if_addr;
-        ip4_addr_t multi_addr;
-        LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
-        inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
-        inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
-        if (optname == IP_ADD_MEMBERSHIP) {
-          if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
-            /* cannot track membership (out of memory) */
-            err = ENOMEM;
-            igmp_err = ERR_OK;
-          } else {
-            igmp_err = igmp_joingroup(&if_addr, &multi_addr);
-          }
-        } else {
-          igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
-          lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
-        }
-        if (igmp_err != ERR_OK) {
-          err = EADDRNOTAVAIL;
-        }
-      }
-      break;
-#endif /* LWIP_IGMP */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-    /* Special case: all IPPROTO_TCP option take an int */
-    LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
-    switch (optname) {
-    case TCP_NODELAY:
-      if (*(const int*)optval) {
-        tcp_nagle_disable(sock->conn->pcb.tcp);
-      } else {
-        tcp_nagle_enable(sock->conn->pcb.tcp);
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
-                  s, (*(const int *)optval)?"on":"off") );
-      break;
-    case TCP_KEEPALIVE:
-      sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
-                  s, sock->conn->pcb.tcp->keep_idle));
-      break;
-
-#if LWIP_TCP_KEEPALIVE
-    case TCP_KEEPIDLE:
-      sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
-                  s, sock->conn->pcb.tcp->keep_idle));
-      break;
-    case TCP_KEEPINTVL:
-      sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
-                  s, sock->conn->pcb.tcp->keep_intvl));
-      break;
-    case TCP_KEEPCNT:
-      sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
-                  s, sock->conn->pcb.tcp->keep_cnt));
-      break;
-#endif /* LWIP_TCP_KEEPALIVE */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_TCP*/
-
-#if LWIP_IPV6
-/* Level: IPPROTO_IPV6 */
-  case IPPROTO_IPV6:
-    switch (optname) {
-    case IPV6_V6ONLY:
-      /* @todo: this does not work for datagram sockets, yet */
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
-      if (*(const int*)optval) {
-        netconn_set_ipv6only(sock->conn, 1);
-      } else {
-        netconn_set_ipv6only(sock->conn, 0);
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
-                  s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
-      break;
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_IPV6 */
-
-#if LWIP_UDP && LWIP_UDPLITE
-  /* Level: IPPROTO_UDPLITE */
-  case IPPROTO_UDPLITE:
-    /* Special case: all IPPROTO_UDPLITE option take an int */
-    LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
-    /* If this is no UDP lite socket, ignore any options. */
-    if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
-      return ENOPROTOOPT;
-    }
-    switch (optname) {
-    case UDPLITE_SEND_CSCOV:
-      if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
-        /* don't allow illegal values! */
-        sock->conn->pcb.udp->chksum_len_tx = 8;
-      } else {
-        sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
-                  s, (*(const int*)optval)) );
-      break;
-    case UDPLITE_RECV_CSCOV:
-      if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
-        /* don't allow illegal values! */
-        sock->conn->pcb.udp->chksum_len_rx = 8;
-      } else {
-        sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
-                  s, (*(const int*)optval)) );
-      break;
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
-                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-#endif /* LWIP_UDP */
-  /* Level: IPPROTO_RAW */
-  case IPPROTO_RAW:
-    switch (optname) {
-#if LWIP_IPV6 && LWIP_RAW
-    case IPV6_CHECKSUM:
-      LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW);
-      if (*(const int *)optval < 0) {
-        sock->conn->pcb.raw->chksum_reqd = 0;
-      } else if (*(const int *)optval & 1) {
-        /* Per RFC3542, odd offsets are not allowed */
-        return EINVAL;
-      } else {
-        sock->conn->pcb.raw->chksum_reqd = 1;
-        sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n",
-                  s, sock->conn->pcb.raw->chksum_reqd));
-      break;
-#endif /* LWIP_IPV6 && LWIP_RAW */
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
-                                  s, optname));
-      err = ENOPROTOOPT;
-      break;
-    }  /* switch (optname) */
-    break;
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
-                s, level, optname));
-    err = ENOPROTOOPT;
-    break;
-  }  /* switch (level) */
-
-  return err;
-}
-
-int
-lwip_ioctl(int s, long cmd, void *argp)
-{
-  struct lwip_sock *sock = get_socket(s);
-  u8_t val;
-#if LWIP_SO_RCVBUF
-  u16_t buflen = 0;
-  int recv_avail;
-#endif /* LWIP_SO_RCVBUF */
-
-  if (!sock) {
-    return -1;
-  }
-
-  switch (cmd) {
-#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
-  case FIONREAD:
-    if (!argp) {
-      sock_set_errno(sock, EINVAL);
-      return -1;
-    }
-#if LWIP_FIONREAD_LINUXMODE
-    if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-      struct pbuf *p;
-      if (sock->lastdata) {
-        p = ((struct netbuf *)sock->lastdata)->p;
-        *((int*)argp) = p->tot_len - sock->lastoffset;
-      } else {
-        struct netbuf *rxbuf;
-        err_t err;
-        if (sock->rcvevent <= 0) {
-          *((int*)argp) = 0;
-        } else {
-          err = netconn_recv(sock->conn, &rxbuf);
-          if (err != ERR_OK) {
-            *((int*)argp) = 0;
-          } else {
-            sock->lastdata = rxbuf;
-            sock->lastoffset = 0;
-            *((int*)argp) = rxbuf->p->tot_len;
-          }
-        }
-      }
-      return 0;
-    }
-#endif /* LWIP_FIONREAD_LINUXMODE */
-
-#if LWIP_SO_RCVBUF
-    /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */
-    SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
-    if (recv_avail < 0) {
-      recv_avail = 0;
-    }
-    *((int*)argp) = recv_avail;
-
-    /* Check if there is data left from the last recv operation. /maq 041215 */
-    if (sock->lastdata) {
-      struct pbuf *p = (struct pbuf *)sock->lastdata;
-      if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
-        p = ((struct netbuf *)p)->p;
-      }
-      buflen = p->tot_len;
-      buflen -= sock->lastoffset;
-
-      *((int*)argp) += buflen;
-    }
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
-    sock_set_errno(sock, 0);
-    return 0;
-#else /* LWIP_SO_RCVBUF */
-    break;
-#endif /* LWIP_SO_RCVBUF */
-#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */
-
-  case (long)FIONBIO:
-    val = 0;
-    if (argp && *(u32_t*)argp) {
-      val = 1;
-    }
-    netconn_set_nonblocking(sock->conn, val);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
-    sock_set_errno(sock, 0);
-    return 0;
-
-  default:
-    break;
-  } /* switch (cmd) */
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
-  sock_set_errno(sock, ENOSYS); /* not yet implemented */
-  return -1;
-}
-
-/** A minimal implementation of fcntl.
- * Currently only the commands F_GETFL and F_SETFL are implemented.
- * Only the flag O_NONBLOCK is implemented.
- */
-int
-lwip_fcntl(int s, int cmd, int val)
-{
-  struct lwip_sock *sock = get_socket(s);
-  int ret = -1;
-
-  if (!sock) {
-    return -1;
-  }
-
-  switch (cmd) {
-  case F_GETFL:
-    ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
-    sock_set_errno(sock, 0);
-    break;
-  case F_SETFL:
-    if ((val & ~O_NONBLOCK) == 0) {
-      /* only O_NONBLOCK, all other bits are zero */
-      netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
-      ret = 0;
-      sock_set_errno(sock, 0);
-    } else {
-      sock_set_errno(sock, ENOSYS); /* not yet implemented */
-    }
-    break;
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
-    sock_set_errno(sock, ENOSYS); /* not yet implemented */
-    break;
-  }
-  return ret;
-}
-
-#if LWIP_IGMP
-/** Register a new IGMP membership. On socket close, the membership is dropped automatically.
- *
- * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
- *
- * @return 1 on success, 0 on failure
- */
-static int
-lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
-{
-  struct lwip_sock *sock = get_socket(s);
-  int i;
-
-  if (!sock) {
-    return 0;
-  }
-
-  for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
-    if (socket_ipv4_multicast_memberships[i].sock == NULL) {
-      socket_ipv4_multicast_memberships[i].sock = sock;
-      ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
-      ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
-      return 1;
-    }
-  }
-  return 0;
-}
-
-/** Unregister a previously registered membership. This prevents dropping the membership
- * on socket close.
- *
- * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
- */
-static void
-lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
-{
-  struct lwip_sock *sock = get_socket(s);
-  int i;
-
-  if (!sock) {
-    return;
-  }
-
-  for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
-    if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
-        ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
-        ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
-      socket_ipv4_multicast_memberships[i].sock = NULL;
-      ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
-      ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
-      return;
-    }
-  }
-}
-
-/** Drop all memberships of a socket that were not dropped explicitly via setsockopt.
- *
- * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK).
- */
-static void
-lwip_socket_drop_registered_memberships(int s)
-{
-  struct lwip_sock *sock = get_socket(s);
-  int i;
-
-  if (!sock) {
-    return;
-  }
-
-  for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
-    if (socket_ipv4_multicast_memberships[i].sock == sock) {
-      ip_addr_t multi_addr, if_addr;
-      ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
-      ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
-      socket_ipv4_multicast_memberships[i].sock = NULL;
-      ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
-      ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
-
-      netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE);
-    }
-  }
-}
-#endif /* LWIP_IGMP */
-#endif /* LWIP_SOCKET */

+ 0 - 518
components/net/lwip-2.0.0/src/api/tcpip.c

@@ -1,518 +0,0 @@
-/**
- * @file
- * Sequential API Main thread module
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/priv/tcpip_priv.h"
-#include "lwip/sys.h"
-#include "lwip/memp.h"
-#include "lwip/mem.h"
-#include "lwip/init.h"
-#include "lwip/ip.h"
-#include "lwip/pbuf.h"
-#include "lwip/etharp.h"
-#include "netif/ethernet.h"
-
-#define TCPIP_MSG_VAR_REF(name)     API_VAR_REF(name)
-#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
-#define TCPIP_MSG_VAR_ALLOC(name)   API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
-#define TCPIP_MSG_VAR_FREE(name)    API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
-
-/* global variables */
-static tcpip_init_done_fn tcpip_init_done;
-static void *tcpip_init_done_arg;
-static sys_mbox_t mbox;
-
-#if LWIP_TCPIP_CORE_LOCKING
-/** The global semaphore to lock the stack. */
-sys_mutex_t lock_tcpip_core;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
-#if LWIP_TIMERS
-/* wait for a message, timeouts are processed while waiting */
-#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
-#else /* LWIP_TIMERS */
-/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
-#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
-#endif /* LWIP_TIMERS */
-
-/**
- * The main lwIP thread. This thread has exclusive access to lwIP core functions
- * (unless access to them is not locked). Other threads communicate with this
- * thread using message boxes.
- *
- * It also starts all the timers to make sure they are running in the right
- * thread context.
- *
- * @param arg unused argument
- */
-static void
-tcpip_thread(void *arg)
-{
-  struct tcpip_msg *msg;
-  LWIP_UNUSED_ARG(arg);
-
-  if (tcpip_init_done != NULL) {
-    tcpip_init_done(tcpip_init_done_arg);
-  }
-
-  LOCK_TCPIP_CORE();
-  while (1) {                          /* MAIN Loop */
-    UNLOCK_TCPIP_CORE();
-    LWIP_TCPIP_THREAD_ALIVE();
-    /* wait for a message, timeouts are processed while waiting */
-    TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
-    LOCK_TCPIP_CORE();
-    if (msg == NULL) {
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
-      LWIP_ASSERT("tcpip_thread: invalid message", 0);
-      continue;
-    }
-    switch (msg->type) {
-#if !LWIP_TCPIP_CORE_LOCKING
-    case TCPIP_MSG_API:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
-      msg->msg.api_msg.function(msg->msg.api_msg.msg);
-      break;
-    case TCPIP_MSG_API_CALL:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
-      msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
-      sys_sem_signal(msg->msg.api_call.sem);
-      break;
-#endif /* !LWIP_TCPIP_CORE_LOCKING */
-
-#if !LWIP_TCPIP_CORE_LOCKING_INPUT
-    case TCPIP_MSG_INPKT:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
-      msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
-      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
-      break;
-#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
-
-#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
-    case TCPIP_MSG_TIMEOUT:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
-      sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
-      memp_free(MEMP_TCPIP_MSG_API, msg);
-      break;
-    case TCPIP_MSG_UNTIMEOUT:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
-      sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
-      memp_free(MEMP_TCPIP_MSG_API, msg);
-      break;
-#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
-
-    case TCPIP_MSG_CALLBACK:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
-      msg->msg.cb.function(msg->msg.cb.ctx);
-      memp_free(MEMP_TCPIP_MSG_API, msg);
-      break;
-
-    case TCPIP_MSG_CALLBACK_STATIC:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
-      msg->msg.cb.function(msg->msg.cb.ctx);
-      break;
-
-    default:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
-      LWIP_ASSERT("tcpip_thread: invalid message", 0);
-      break;
-    }
-  }
-}
-
-/**
- * Pass a received packet to tcpip_thread for input processing
- *
- * @param p the received packet
- * @param inp the network interface on which the packet was received
- * @param input_fn input function to call
- */
-err_t
-tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
-{
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-  err_t ret;
-  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
-  LOCK_TCPIP_CORE();
-  ret = input_fn(p, inp);
-  UNLOCK_TCPIP_CORE();
-  return ret;
-#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
-  struct tcpip_msg *msg;
-
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
-  if (msg == NULL) {
-    return ERR_MEM;
-  }
-
-  msg->type = TCPIP_MSG_INPKT;
-  msg->msg.inp.p = p;
-  msg->msg.inp.netif = inp;
-  msg->msg.inp.input_fn = input_fn;
-  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
-    memp_free(MEMP_TCPIP_MSG_INPKT, msg);
-    return ERR_MEM;
-  }
-  return ERR_OK;
-#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
-}
-
-/**
- * @ingroup lwip_os
- * Pass a received packet to tcpip_thread for input processing with
- * ethernet_input or ip_input. Don't call directly, pass to netif_add()
- * and call netif->input().
- *
- * @param p the received packet, p->payload pointing to the Ethernet header or
- *          to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
- *          NETIF_FLAG_ETHERNET flags)
- * @param inp the network interface on which the packet was received
- */
-err_t
-tcpip_input(struct pbuf *p, struct netif *inp)
-{
-#if LWIP_ETHERNET
-  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
-    return tcpip_inpkt(p, inp, ethernet_input);
-  } else
-#endif /* LWIP_ETHERNET */
-  return tcpip_inpkt(p, inp, ip_input);
-}
-
-/**
- * Call a specific function in the thread context of
- * tcpip_thread for easy access synchronization.
- * A function called in that way may access lwIP core code
- * without fearing concurrent access.
- *
- * @param function the function to call
- * @param ctx parameter passed to f
- * @param block 1 to block until the request is posted, 0 to non-blocking mode
- * @return ERR_OK if the function was called, another err_t if not
- */
-err_t
-tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
-{
-  struct tcpip_msg *msg;
-
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
-  if (msg == NULL) {
-    return ERR_MEM;
-  }
-
-  msg->type = TCPIP_MSG_CALLBACK;
-  msg->msg.cb.function = function;
-  msg->msg.cb.ctx = ctx;
-  if (block) {
-    sys_mbox_post(&mbox, msg);
-  } else {
-    if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
-      memp_free(MEMP_TCPIP_MSG_API, msg);
-      return ERR_MEM;
-    }
-  }
-  return ERR_OK;
-}
-
-#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
-/**
- * call sys_timeout in tcpip_thread
- *
- * @param msecs time in milliseconds for timeout
- * @param h function to be called on timeout
- * @param arg argument to pass to timeout function h
- * @return ERR_MEM on memory error, ERR_OK otherwise
- */
-err_t
-tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
-{
-  struct tcpip_msg *msg;
-
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
-  if (msg == NULL) {
-    return ERR_MEM;
-  }
-
-  msg->type = TCPIP_MSG_TIMEOUT;
-  msg->msg.tmo.msecs = msecs;
-  msg->msg.tmo.h = h;
-  msg->msg.tmo.arg = arg;
-  sys_mbox_post(&mbox, msg);
-  return ERR_OK;
-}
-
-/**
- * call sys_untimeout in tcpip_thread
- *
- * @param h function to be called on timeout
- * @param arg argument to pass to timeout function h
- * @return ERR_MEM on memory error, ERR_OK otherwise
- */
-err_t
-tcpip_untimeout(sys_timeout_handler h, void *arg)
-{
-  struct tcpip_msg *msg;
-
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
-  if (msg == NULL) {
-    return ERR_MEM;
-  }
-
-  msg->type = TCPIP_MSG_UNTIMEOUT;
-  msg->msg.tmo.h = h;
-  msg->msg.tmo.arg = arg;
-  sys_mbox_post(&mbox, msg);
-  return ERR_OK;
-}
-#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
-
-
-/**
- * Sends a message to TCPIP thread to call a function. Caller thread blocks on
- * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
- * this has to be done by the user.
- * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
- * with least runtime overhead.
- *
- * @param fn function to be called from TCPIP thread
- * @param apimsg argument to API function
- * @param sem semaphore to wait on
- * @return ERR_OK if the function was called, another err_t if not
- */
-err_t
-tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem)
-{
-#if LWIP_TCPIP_CORE_LOCKING
-  LWIP_UNUSED_ARG(sem);
-  LOCK_TCPIP_CORE();
-  fn(apimsg);
-  UNLOCK_TCPIP_CORE();
-  return ERR_OK;
-#else /* LWIP_TCPIP_CORE_LOCKING */
-  TCPIP_MSG_VAR_DECLARE(msg);
-
-  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  TCPIP_MSG_VAR_ALLOC(msg);
-  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
-  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
-  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
-  sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
-  sys_arch_sem_wait(sem, 0);
-  TCPIP_MSG_VAR_FREE(msg);
-  return ERR_OK;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-}
-
-/**
- * Synchronously calls function in TCPIP thread and waits for its completion.
- * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
- * LWIP_NETCONN_SEM_PER_THREAD. 
- * If not, a semaphore is created and destroyed on every call which is usually
- * an expensive/slow operation.
- * @param fn Function to call
- * @param call Call parameters
- * @return Return value from tcpip_api_call_fn
- */
-err_t
-tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
-{
-#if LWIP_TCPIP_CORE_LOCKING
-  err_t err;
-  LOCK_TCPIP_CORE();
-  err = fn(call);
-  UNLOCK_TCPIP_CORE();
-  return err;
-#else /* LWIP_TCPIP_CORE_LOCKING */
-  TCPIP_MSG_VAR_DECLARE(msg);
-
-#if !LWIP_NETCONN_SEM_PER_THREAD
-  err_t err = sys_sem_new(&call->sem, 0);
-  if (err != ERR_OK) {
-    return err;
-  }
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-
-  TCPIP_MSG_VAR_ALLOC(msg);
-  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
-  TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
-  TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
-#if LWIP_NETCONN_SEM_PER_THREAD
-  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
-#else /* LWIP_NETCONN_SEM_PER_THREAD */
-  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-  sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
-  sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
-  TCPIP_MSG_VAR_FREE(msg);
-
-#if !LWIP_NETCONN_SEM_PER_THREAD
-  sys_sem_free(&call->sem);
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-  return call->err;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-}
-
-/**
- * Allocate a structure for a static callback message and initialize it.
- * This is intended to be used to send "static" messages from interrupt context.
- *
- * @param function the function to call
- * @param ctx parameter passed to function
- * @return a struct pointer to pass to tcpip_trycallback().
- */
-struct tcpip_callback_msg*
-tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
-{
-  struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
-  if (msg == NULL) {
-    return NULL;
-  }
-  msg->type = TCPIP_MSG_CALLBACK_STATIC;
-  msg->msg.cb.function = function;
-  msg->msg.cb.ctx = ctx;
-  return (struct tcpip_callback_msg*)msg;
-}
-
-/**
- * Free a callback message allocated by tcpip_callbackmsg_new().
- *
- * @param msg the message to free
- */
-void
-tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
-{
-  memp_free(MEMP_TCPIP_MSG_API, msg);
-}
-
-/**
- * Try to post a callback-message to the tcpip_thread mbox
- * This is intended to be used to send "static" messages from interrupt context.
- *
- * @param msg pointer to the message to post
- * @return sys_mbox_trypost() return code
- */
-err_t
-tcpip_trycallback(struct tcpip_callback_msg* msg)
-{
-  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
-  return sys_mbox_trypost(&mbox, msg);
-}
-
-/**
- * @ingroup lwip_os
- * Initialize this module:
- * - initialize all sub modules
- * - start the tcpip_thread
- *
- * @param initfunc a function to call when tcpip_thread is running and finished initializing
- * @param arg argument to pass to initfunc
- */
-void
-tcpip_init(tcpip_init_done_fn initfunc, void *arg)
-{
-  lwip_init();
-
-  tcpip_init_done = initfunc;
-  tcpip_init_done_arg = arg;
-  if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
-    LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
-  }
-#if LWIP_TCPIP_CORE_LOCKING
-  if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
-    LWIP_ASSERT("failed to create lock_tcpip_core", 0);
-  }
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
-  sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
-}
-
-/**
- * Simple callback function used with tcpip_callback to free a pbuf
- * (pbuf_free has a wrong signature for tcpip_callback)
- *
- * @param p The pbuf (chain) to be dereferenced.
- */
-static void
-pbuf_free_int(void *p)
-{
-  struct pbuf *q = (struct pbuf *)p;
-  pbuf_free(q);
-}
-
-/**
- * A simple wrapper function that allows you to free a pbuf from interrupt context.
- *
- * @param p The pbuf (chain) to be dereferenced.
- * @return ERR_OK if callback could be enqueued, an err_t if not
- */
-err_t
-pbuf_free_callback(struct pbuf *p)
-{
-  return tcpip_callback_with_block(pbuf_free_int, p, 0);
-}
-
-/**
- * A simple wrapper function that allows you to free heap memory from
- * interrupt context.
- *
- * @param m the heap memory to free
- * @return ERR_OK if callback could be enqueued, an err_t if not
- */
-err_t
-mem_free_callback(void *m)
-{
-  return tcpip_callback_with_block(mem_free, m, 0);
-}
-
-#endif /* !NO_SYS */

+ 0 - 179
components/net/lwip-2.0.0/src/apps/httpd/fs.c

@@ -1,179 +0,0 @@
-/*
- * 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;
-}

+ 0 - 21
components/net/lwip-2.0.0/src/apps/httpd/fs/404.html

@@ -1,21 +0,0 @@
-<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>
-	  &nbsp;
-	</td></tr>
-      </table>
-</body>
-</html>

BIN
components/net/lwip-2.0.0/src/apps/httpd/fs/img/sics.gif


+ 0 - 47
components/net/lwip-2.0.0/src/apps/httpd/fs/index.html

@@ -1,47 +0,0 @@
-<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>
-	  &nbsp;
-	</td></tr>
-      </table>
-</body>
-</html>
-

+ 0 - 298
components/net/lwip-2.0.0/src/apps/httpd/fsdata.c

@@ -1,298 +0,0 @@
-#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
-

+ 0 - 50
components/net/lwip-2.0.0/src/apps/httpd/fsdata.h

@@ -1,50 +0,0 @@
-/*
- * 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 */

+ 0 - 2619
components/net/lwip-2.0.0/src/apps/httpd/httpd.c

@@ -1,2619 +0,0 @@
-/**
- * @file
- * LWIP HTTP server implementation
- */
-
-/*
- * 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>
- *         Simon Goldschmidt
- *
- */
-
-/**
- * @defgroup httpd HTTP server
- * @ingroup apps
- *
- * This httpd supports for a
- * rudimentary server-side-include facility which will replace tags of the form
- * <!--#tag--> in any file whose extension is .shtml, .shtm or .ssi with
- * strings provided by an include handler whose pointer is provided to the
- * module via function http_set_ssi_handler().
- * Additionally, a simple common
- * gateway interface (CGI) handling mechanism has been added to allow clients
- * to hook functions to particular request URIs.
- *
- * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h.
- * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h.
- *
- * By default, the server assumes that HTTP headers are already present in
- * each file stored in the file system.  By defining LWIP_HTTPD_DYNAMIC_HEADERS in
- * lwipopts.h, this behavior can be changed such that the server inserts the
- * headers automatically based on the extension of the file being served.  If
- * this mode is used, be careful to ensure that the file system image used
- * does not already contain the header information.
- *
- * File system images without headers can be created using the makefsfile
- * tool with the -h command line option.
- *
- *
- * Notes about valid SSI tags
- * --------------------------
- *
- * The following assumptions are made about tags used in SSI markers:
- *
- * 1. No tag may contain '-' or whitespace characters within the tag name.
- * 2. Whitespace is allowed between the tag leadin "<!--#" and the start of
- *    the tag name and between the tag name and the leadout string "-->".
- * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters.
- *
- * Notes on CGI usage
- * ------------------
- *
- * The simple CGI support offered here works with GET method requests only
- * and can handle up to 16 parameters encoded into the URI. The handler
- * function may not write directly to the HTTP output but must return a
- * filename that the HTTP server will send to the browser as a response to
- * the incoming CGI request.
- *
- *
- *
- * The list of supported file types is quite short, so if makefsdata complains
- * about an unknown extension, make sure to add it (and its doctype) to
- * the 'g_psHTTPHeaders' list.
- */
-#include "lwip/init.h"
-#include "lwip/apps/httpd.h"
-#include "lwip/debug.h"
-#include "lwip/stats.h"
-#include "lwip/apps/fs.h"
-#include "httpd_structs.h"
-#include "lwip/def.h"
-#include "lwip/ip.h"
-#include "lwip/tcp.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#if LWIP_TCP
-
-/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */
-#define MIN_REQ_LEN   7
-
-#define CRLF "\r\n"
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-#define HTTP11_CONNECTIONKEEPALIVE  "Connection: keep-alive"
-#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive"
-#endif
-
-/** These defines check whether tcp_write has to copy data or not */
-
-/** This was TI's check whether to let TCP copy data or not
- * \#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY)
- */
-#ifndef HTTP_IS_DATA_VOLATILE
-#if LWIP_HTTPD_SSI
-/* Copy for SSI files, no copy for non-SSI files */
-#define HTTP_IS_DATA_VOLATILE(hs)   ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0)
-#else /* LWIP_HTTPD_SSI */
-/** Default: don't copy if the data is sent from file-system directly */
-#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \
-                                   (const char*)hs->handle->data + hs->handle->len - hs->left)) \
-                                   ? 0 : TCP_WRITE_FLAG_COPY)
-#endif /* LWIP_HTTPD_SSI */
-#endif
-
-/** Default: headers are sent from ROM */
-#ifndef HTTP_IS_HDR_VOLATILE
-#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0
-#endif
-
-/* Return values for http_send_*() */
-#define HTTP_DATA_TO_SEND_BREAK    2
-#define HTTP_DATA_TO_SEND_CONTINUE 1
-#define HTTP_NO_DATA_TO_SEND       0
-
-typedef struct
-{
-  const char *name;
-  u8_t shtml;
-} default_filename;
-
-const default_filename g_psDefaultFilenames[] = {
-  {"/index.shtml", 1 },
-  {"/index.ssi",   1 },
-  {"/index.shtm",  1 },
-  {"/index.html",  0 },
-  {"/index.htm",   0 }
-};
-
-#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) /   \
-                               sizeof(default_filename))
-
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-/** HTTP request is copied here from pbufs for simple parsing */
-static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1];
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-
-#if LWIP_HTTPD_SUPPORT_POST
-#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN
-#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN
-#endif
-#endif
-#ifndef LWIP_HTTPD_URI_BUF_LEN
-#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN
-#endif
-#if LWIP_HTTPD_URI_BUF_LEN
-/* Filename for response file to send when POST is finished or
- * search for default files when a directory is requested. */
-static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN+1];
-#endif
-
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-/* The number of individual strings that comprise the headers sent before each
- * requested file.
- */
-#define NUM_FILE_HDR_STRINGS 5
-#define HDR_STRINGS_IDX_HTTP_STATUS          0 /* e.g. "HTTP/1.0 200 OK\r\n" */
-#define HDR_STRINGS_IDX_SERVER_NAME          1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */
-#define HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */
-#define HDR_STRINGS_IDX_CONTENT_LEN_NR       3 /* the byte count, when content-length is used */
-#define HDR_STRINGS_IDX_CONTENT_TYPE         4 /* the content type (or default answer content type including default document) */
-
-/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */
-#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3
-#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE
-/* The dynamically generated Content-Length buffer shall be able to work with
-   ~953 MB (9 digits) */
-#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE   (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET)
-#endif
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-
-#if LWIP_HTTPD_SSI
-
-#define HTTPD_LAST_TAG_PART 0xFFFF
-
-enum tag_check_state {
-  TAG_NONE,       /* Not processing an SSI tag */
-  TAG_LEADIN,     /* Tag lead in "<!--#" being processed */
-  TAG_FOUND,      /* Tag name being read, looking for lead-out start */
-  TAG_LEADOUT,    /* Tag lead out "-->" being processed */
-  TAG_SENDING     /* Sending tag replacement string */
-};
-
-struct http_ssi_state {
-  const char *parsed;     /* Pointer to the first unparsed byte in buf. */
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-  const char *tag_started;/* Pointer to the first opening '<' of the tag. */
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */
-  const char *tag_end;    /* Pointer to char after the closing '>' of the tag. */
-  u32_t parse_left; /* Number of unparsed bytes in buf. */
-  u16_t tag_index;   /* Counter used by tag parsing state machine */
-  u16_t tag_insert_len; /* Length of insert in string tag_insert */
-#if LWIP_HTTPD_SSI_MULTIPART
-  u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-  u8_t tag_name_len; /* Length of the tag name in string tag_name */
-  char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */
-  char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */
-  enum tag_check_state tag_state; /* State of the tag processor */
-};
-#endif /* LWIP_HTTPD_SSI */
-
-struct http_state {
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-  struct http_state *next;
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-  struct fs_file file_handle;
-  struct fs_file *handle;
-  const char *file;       /* Pointer to first unsent byte in buf. */
-
-  struct tcp_pcb *pcb;
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-  struct pbuf *req;
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-
-#if LWIP_HTTPD_DYNAMIC_FILE_READ
-  char *buf;        /* File read buffer. */
-  int buf_len;      /* Size of file read buffer, buf. */
-#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
-  u32_t left;       /* Number of unsent bytes in buf. */
-  u8_t retries;
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-  u8_t keepalive;
-#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-#if LWIP_HTTPD_SSI
-  struct http_ssi_state *ssi;
-#endif /* LWIP_HTTPD_SSI */
-#if LWIP_HTTPD_CGI
-  char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */
-  char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */
-#endif /* LWIP_HTTPD_CGI */
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-  const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */
-  char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE];
-  u16_t hdr_pos;     /* The position of the first unsent header byte in the
-                        current string */
-  u16_t hdr_index;   /* The index of the hdr string currently being sent. */
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-#if LWIP_HTTPD_TIMING
-  u32_t time_started;
-#endif /* LWIP_HTTPD_TIMING */
-#if LWIP_HTTPD_SUPPORT_POST
-  u32_t post_content_len_left;
-#if LWIP_HTTPD_POST_MANUAL_WND
-  u32_t unrecved_bytes;
-  u8_t no_auto_wnd;
-  u8_t post_finished;
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-#endif /* LWIP_HTTPD_SUPPORT_POST*/
-};
-
-#if HTTPD_USE_MEM_POOL
-LWIP_MEMPOOL_DECLARE(HTTPD_STATE,     MEMP_NUM_PARALLEL_HTTPD_CONNS,     sizeof(struct http_state),     "HTTPD_STATE")
-#if LWIP_HTTPD_SSI
-LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE")
-#define HTTP_FREE_SSI_STATE(x)  LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x))
-#define HTTP_ALLOC_SSI_STATE()  (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE)
-#endif /* LWIP_HTTPD_SSI */
-#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE)
-#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x))
-#else /* HTTPD_USE_MEM_POOL */
-#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state))
-#define HTTP_FREE_HTTP_STATE(x) mem_free(x)
-#if LWIP_HTTPD_SSI
-#define HTTP_ALLOC_SSI_STATE()  (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state))
-#define HTTP_FREE_SSI_STATE(x)  mem_free(x)
-#endif /* LWIP_HTTPD_SSI */
-#endif /* HTTPD_USE_MEM_POOL */
-
-static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs);
-static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn);
-static err_t http_find_file(struct http_state *hs, const char *uri, int is_09);
-static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char* params);
-static err_t http_poll(void *arg, struct tcp_pcb *pcb);
-static u8_t http_check_eof(struct tcp_pcb *pcb, struct http_state *hs);
-#if LWIP_HTTPD_FS_ASYNC_READ
-static void http_continue(void *connection);
-#endif /* LWIP_HTTPD_FS_ASYNC_READ */
-
-#if LWIP_HTTPD_SSI
-/* SSI insert handler function pointer. */
-tSSIHandler g_pfnSSIHandler;
-#if !LWIP_HTTPD_SSI_RAW
-int g_iNumTags;
-const char **g_ppcTags;
-#endif /* !LWIP_HTTPD_SSI_RAW */
-
-#define LEN_TAG_LEAD_IN 5
-const char * const g_pcTagLeadIn = "<!--#";
-
-#define LEN_TAG_LEAD_OUT 3
-const char * const g_pcTagLeadOut = "-->";
-#endif /* LWIP_HTTPD_SSI */
-
-#if LWIP_HTTPD_CGI
-/* CGI handler information */
-const tCGI *g_pCGIs;
-int g_iNumCGIs;
-int http_cgi_paramcount;
-#define http_cgi_params     hs->params
-#define http_cgi_param_vals hs->param_vals
-#elif LWIP_HTTPD_CGI_SSI
-char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */
-char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */
-#endif /* LWIP_HTTPD_CGI */
-
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-/** global list of active HTTP connections, use to kill the oldest when
-    running out of memory */
-static struct http_state *http_connections;
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-static void
-http_kill_oldest_connection(u8_t ssi_required)
-{
-  struct http_state *hs = http_connections;
-  struct http_state *hs_free_next = NULL;
-  while(hs && hs->next) {
-#if LWIP_HTTPD_SSI
-    if (ssi_required) {
-      if (hs->next->ssi != NULL) {
-        hs_free_next = hs;
-      }
-    } else
-#else /* LWIP_HTTPD_SSI */
-    LWIP_UNUSED_ARG(ssi_required);
-#endif /* LWIP_HTTPD_SSI */
-    {
-      hs_free_next = hs;
-    }
-    LWIP_ASSERT("broken list", hs != hs->next);
-    hs = hs->next;
-  }
-  if (hs_free_next != NULL) {
-    LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL);
-    LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL);
-    /* send RST when killing a connection because of memory shortage */
-    http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */
-  }
-}
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-
-#if LWIP_HTTPD_SSI
-/** Allocate as struct http_ssi_state. */
-static struct http_ssi_state*
-http_ssi_state_alloc(void)
-{
-  struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE();
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-  if (ret == NULL) {
-    http_kill_oldest_connection(1);
-    ret = HTTP_ALLOC_SSI_STATE();
-  }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-  if (ret != NULL) {
-    memset(ret, 0, sizeof(struct http_ssi_state));
-  }
-  return ret;
-}
-
-/** Free a struct http_ssi_state. */
-static void
-http_ssi_state_free(struct http_ssi_state *ssi)
-{
-  if (ssi != NULL) {
-    HTTP_FREE_SSI_STATE(ssi);
-  }
-}
-#endif /* LWIP_HTTPD_SSI */
-
-/** Initialize a struct http_state.
- */
-static void
-http_state_init(struct http_state* hs)
-{
-  /* Initialize the structure. */
-  memset(hs, 0, sizeof(struct http_state));
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-  /* Indicate that the headers are not yet valid */
-  hs->hdr_index = NUM_FILE_HDR_STRINGS;
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-}
-
-/** Allocate a struct http_state. */
-static struct http_state*
-http_state_alloc(void)
-{
-  struct http_state *ret = HTTP_ALLOC_HTTP_STATE();
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-  if (ret == NULL) {
-    http_kill_oldest_connection(0);
-    ret = HTTP_ALLOC_HTTP_STATE();
-  }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-  if (ret != NULL) {
-    http_state_init(ret);
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    /* add the connection to the list */
-    if (http_connections == NULL) {
-      http_connections = ret;
-    } else {
-      struct http_state *last;
-      for(last = http_connections; last->next != NULL; last = last->next);
-      LWIP_ASSERT("last != NULL", last != NULL);
-      last->next = ret;
-    }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-  }
-  return ret;
-}
-
-/** Free a struct http_state.
- * Also frees the file data if dynamic.
- */
-static void
-http_state_eof(struct http_state *hs)
-{
-  if(hs->handle) {
-#if LWIP_HTTPD_TIMING
-    u32_t ms_needed = sys_now() - hs->time_started;
-    u32_t needed = LWIP_MAX(1, (ms_needed/100));
-    LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n",
-      ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed)));
-#endif /* LWIP_HTTPD_TIMING */
-    fs_close(hs->handle);
-    hs->handle = NULL;
-  }
-#if LWIP_HTTPD_DYNAMIC_FILE_READ
-  if (hs->buf != NULL) {
-    mem_free(hs->buf);
-    hs->buf = NULL;
-  }
-#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
-#if LWIP_HTTPD_SSI
-  if (hs->ssi) {
-    http_ssi_state_free(hs->ssi);
-    hs->ssi = NULL;
-  }
-#endif /* LWIP_HTTPD_SSI */
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-  if (hs->req) {
-    pbuf_free(hs->req);
-    hs->req = NULL;
-  }
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-}
-
-/** Free a struct http_state.
- * Also frees the file data if dynamic.
- */
-static void
-http_state_free(struct http_state *hs)
-{
-  if (hs != NULL) {
-    http_state_eof(hs);
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    /* take the connection off the list */
-    if (http_connections) {
-      if (http_connections == hs) {
-        http_connections = hs->next;
-      } else {
-        struct http_state *last;
-        for(last = http_connections; last->next != NULL; last = last->next) {
-          if (last->next == hs) {
-            last->next = hs->next;
-            break;
-          }
-        }
-      }
-    }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
-    HTTP_FREE_HTTP_STATE(hs);
-  }
-}
-
-/** Call tcp_write() in a loop trying smaller and smaller length
- *
- * @param pcb tcp_pcb to send
- * @param ptr Data to send
- * @param length Length of data to send (in/out: on return, contains the
- *        amount of data sent)
- * @param apiflags directly passed to tcp_write
- * @return the return value of tcp_write
- */
-static err_t
-http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags)
-{
-  u16_t len, max_len;
-  err_t err;
-  LWIP_ASSERT("length != NULL", length != NULL);
-  len = *length;
-  if (len == 0) {
-    return ERR_OK;
-  }
-  /* We cannot send more data than space available in the send buffer. */
-  max_len = tcp_sndbuf(pcb);
-  if (max_len < len) {
-    len = max_len;
-  }
-#ifdef HTTPD_MAX_WRITE_LEN
-  /* Additional limitation: e.g. don't enqueue more than 2*mss at once */
-  max_len = HTTPD_MAX_WRITE_LEN(pcb);
-  if(len > max_len) {
-    len = max_len;
-  }
-#endif /* HTTPD_MAX_WRITE_LEN */
-  do {
-    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying go send %d bytes\n", len));
-    err = tcp_write(pcb, ptr, len, apiflags);
-    if (err == ERR_MEM) {
-      if ((tcp_sndbuf(pcb) == 0) ||
-        (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) {
-          /* no need to try smaller sizes */
-          len = 1;
-      } else {
-        len /= 2;
-      }
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, 
-        ("Send failed, trying less (%d bytes)\n", len));
-    }
-  } while ((err == ERR_MEM) && (len > 1));
-
-  if (err == ERR_OK) {
-    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len));
-    *length = len;
-  } else {
-    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err)));
-    *length = 0;
-  }
-
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-   /* ensure nagle is normally enabled (only disabled for persistent connections
-      when all data has been enqueued but the connection stays open for the next
-      request */
-   tcp_nagle_enable(pcb);
-#endif
-
-  return err;
-}
-
-/**
- * The connection shall be actively closed (using RST to close from fault states).
- * Reset the sent- and recv-callbacks.
- *
- * @param pcb the tcp pcb to reset callbacks
- * @param hs connection state to free
- */
-static err_t
-http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn)
-{
-  err_t err;
-  LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb));
-
-#if LWIP_HTTPD_SUPPORT_POST
-  if (hs != NULL) {
-    if ((hs->post_content_len_left != 0)
-#if LWIP_HTTPD_POST_MANUAL_WND
-       || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0))
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-       ) {
-      /* make sure the post code knows that the connection is closed */
-      http_uri_buf[0] = 0;
-      httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN);
-    }
-  }
-#endif /* LWIP_HTTPD_SUPPORT_POST*/
-
-
-  tcp_arg(pcb, NULL);
-  tcp_recv(pcb, NULL);
-  tcp_err(pcb, NULL);
-  tcp_poll(pcb, NULL, 0);
-  tcp_sent(pcb, NULL);
-  if (hs != NULL) {
-    http_state_free(hs);
-  }
-
-  if (abort_conn) {
-    tcp_abort(pcb);
-    return ERR_OK;
-  }
-  err = tcp_close(pcb);
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb));
-    /* error closing, try again later in poll */
-    tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL);
-  }
-  return err;
-}
-
-/**
- * The connection shall be actively closed.
- * Reset the sent- and recv-callbacks.
- *
- * @param pcb the tcp pcb to reset callbacks
- * @param hs connection state to free
- */
-static err_t
-http_close_conn(struct tcp_pcb *pcb, struct http_state *hs)
-{
-   return http_close_or_abort_conn(pcb, hs, 0);
-}
-
-/** End of file: either close the connection (Connection: close) or
- * close the file (Connection: keep-alive)
- */
-static void
-http_eof(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  /* HTTP/1.1 persistent connection? (Not supported for SSI) */
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-  if (hs->keepalive) {
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    struct http_state* next = hs->next;
-#endif
-    http_state_eof(hs);
-    http_state_init(hs);
-    /* restore state: */
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    hs->next = next;
-#endif
-    hs->pcb = pcb;
-    hs->keepalive = 1;
-    /* ensure nagle doesn't interfere with sending all data as fast as possible: */
-    tcp_nagle_disable(pcb);
-  } else
-#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-  {
-    http_close_conn(pcb, hs);
-  }
-}
-
-#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI
-/**
- * Extract URI parameters from the parameter-part of an URI in the form
- * "test.cgi?x=y" @todo: better explanation!
- * Pointers to the parameters are stored in hs->param_vals.
- *
- * @param hs http connection state
- * @param params pointer to the NULL-terminated parameter string from the URI
- * @return number of parameters extracted
- */
-static int
-extract_uri_parameters(struct http_state *hs, char *params)
-{
-  char *pair;
-  char *equals;
-  int loop;
-
-  LWIP_UNUSED_ARG(hs);
-
-  /* If we have no parameters at all, return immediately. */
-  if(!params || (params[0] == '\0')) {
-      return(0);
-  }
-
-  /* Get a pointer to our first parameter */
-  pair = params;
-
-  /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the
-   * remainder (if any) */
-  for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) {
-
-    /* Save the name of the parameter */
-    http_cgi_params[loop] = pair;
-
-    /* Remember the start of this name=value pair */
-    equals = pair;
-
-    /* Find the start of the next name=value pair and replace the delimiter
-     * with a 0 to terminate the previous pair string. */
-    pair = strchr(pair, '&');
-    if(pair) {
-      *pair = '\0';
-      pair++;
-    } else {
-       /* We didn't find a new parameter so find the end of the URI and
-        * replace the space with a '\0' */
-        pair = strchr(equals, ' ');
-        if(pair) {
-            *pair = '\0';
-        }
-
-        /* Revert to NULL so that we exit the loop as expected. */
-        pair = NULL;
-    }
-
-    /* Now find the '=' in the previous pair, replace it with '\0' and save
-     * the parameter value string. */
-    equals = strchr(equals, '=');
-    if(equals) {
-      *equals = '\0';
-      http_cgi_param_vals[loop] = equals + 1;
-    } else {
-      http_cgi_param_vals[loop] = NULL;
-    }
-  }
-
-  return loop;
-}
-#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */
-
-#if LWIP_HTTPD_SSI
-/**
- * Insert a tag (found in an shtml in the form of "<!--#tagname-->" into the file.
- * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement
- * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN).
- * The amount of data written is stored to ssi->tag_insert_len.
- *
- * @todo: return tag_insert_len - maybe it can be removed from struct http_state?
- *
- * @param hs http connection state
- */
-static void
-get_tag_insert(struct http_state *hs)
-{
-#if LWIP_HTTPD_SSI_RAW
-  const char* tag;
-#else /* LWIP_HTTPD_SSI_RAW */
-  int tag;
-#endif /* LWIP_HTTPD_SSI_RAW */
-  size_t len;
-  struct http_ssi_state *ssi;
-#if LWIP_HTTPD_SSI_MULTIPART
-  u16_t current_tag_part;
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-
-  LWIP_ASSERT("hs != NULL", hs != NULL);
-  ssi = hs->ssi;
-  LWIP_ASSERT("ssi != NULL", ssi != NULL);
-#if LWIP_HTTPD_SSI_MULTIPART
-  current_tag_part = ssi->tag_part;
-  ssi->tag_part = HTTPD_LAST_TAG_PART;
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-#if LWIP_HTTPD_SSI_RAW
-  tag = ssi->tag_name;
-#endif
-
-  if(g_pfnSSIHandler
-#if !LWIP_HTTPD_SSI_RAW
-     && g_ppcTags && g_iNumTags
-#endif /* !LWIP_HTTPD_SSI_RAW */
-     ) {
-
-    /* Find this tag in the list we have been provided. */
-#if LWIP_HTTPD_SSI_RAW
-    {
-#else /* LWIP_HTTPD_SSI_RAW */
-    for(tag = 0; tag < g_iNumTags; tag++) {
-      if(strcmp(ssi->tag_name, g_ppcTags[tag]) == 0)
-#endif /* LWIP_HTTPD_SSI_RAW */
-      {
-        ssi->tag_insert_len = g_pfnSSIHandler(tag, ssi->tag_insert,
-           LWIP_HTTPD_MAX_TAG_INSERT_LEN
-#if LWIP_HTTPD_SSI_MULTIPART
-           , current_tag_part, &ssi->tag_part
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-#if LWIP_HTTPD_FILE_STATE
-           , (hs->handle ? hs->handle->state : NULL)
-#endif /* LWIP_HTTPD_FILE_STATE */
-           );
-#if LWIP_HTTPD_SSI_RAW
-        if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN)
-#endif /* LWIP_HTTPD_SSI_RAW */
-        {
-          return;
-        }
-      }
-    }
-  }
-
-  /* If we drop out, we were asked to serve a page which contains tags that
-   * we don't have a handler for. Merely echo back the tags with an error
-   * marker. */
-#define UNKNOWN_TAG1_TEXT "<b>***UNKNOWN TAG "
-#define UNKNOWN_TAG1_LEN  18
-#define UNKNOWN_TAG2_TEXT "***</b>"
-#define UNKNOWN_TAG2_LEN  7
-  len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name),
-    LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN)));
-  MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN);
-  MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len);
-  MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN);
-  ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0;
-
-  len = strlen(ssi->tag_insert);
-  LWIP_ASSERT("len <= 0xffff", len <= 0xffff);
-  ssi->tag_insert_len = (u16_t)len;
-}
-#endif /* LWIP_HTTPD_SSI */
-
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-/**
- * Generate the relevant HTTP headers for the given filename and write
- * them into the supplied buffer.
- */
-static void
-get_http_headers(struct http_state *hs, const char *uri)
-{
-  size_t content_type;
-  char *tmp;
-  char *ext;
-  char *vars;
-  u8_t add_content_len;
-
-  /* In all cases, the second header we send is the server identification
-     so set it here. */
-  hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
-  hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = NULL;
-  hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL;
-
-  /* Is this a normal file or the special case we use to send back the
-     default "404: Page not found" response? */
-  if (uri == NULL) {
-    hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-    if (hs->keepalive) {
-      hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT];
-    } else
-#endif
-    {
-      hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
-    }
-
-    /* Set up to send the first header string. */
-    hs->hdr_index = 0;
-    hs->hdr_pos = 0;
-    return;
-  }
-  /* We are dealing with a particular filename. Look for one other
-      special case.  We assume that any filename with "404" in it must be
-      indicative of a 404 server error whereas all other files require
-      the 200 OK header. */
-  if (strstr(uri, "404")) {
-    hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
-  } else if (strstr(uri, "400")) {
-    hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST];
-  } else if (strstr(uri, "501")) {
-    hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL];
-  } else {
-    hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK];
-  }
-
-  /* Determine if the URI has any variables and, if so, temporarily remove 
-      them. */
-  vars = strchr(uri, '?');
-  if(vars) {
-    *vars = '\0';
-  }
-
-  /* Get a pointer to the file extension.  We find this by looking for the
-      last occurrence of "." in the filename passed. */
-  ext = NULL;
-  tmp = strchr(uri, '.');
-  while (tmp) {
-    ext = tmp + 1;
-    tmp = strchr(ext, '.');
-  }
-  if (ext != NULL) {
-    /* Now determine the content type and add the relevant header for that. */
-    for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) {
-      /* Have we found a matching extension? */
-      if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) {
-        break;
-      }
-    }
-  } else {
-    content_type = NUM_HTTP_HEADERS;
-  }
-
-  /* Reinstate the parameter marker if there was one in the original URI. */
-  if (vars) {
-    *vars = '?';
-  }
-
-#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI
-  /* Does the URL passed have any file extension?  If not, we assume it
-     is a special-case URL used for control state notification and we do
-     not send any HTTP headers with the response. */
-  if (!ext) {
-    /* Force the header index to a value indicating that all headers
-       have already been sent. */
-    hs->hdr_index = NUM_FILE_HDR_STRINGS;
-    return;
-  }
-#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */
-  add_content_len = 1;
-  /* Did we find a matching extension? */
-  if(content_type < NUM_HTTP_HEADERS) {
-    /* yes, store it */
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type;
-  } else if (!ext) {
-    /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP;
-  } else {
-    /* No - use the default, plain text file type. */
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE;
-  }
-  /* Add content-length header? */
-#if LWIP_HTTPD_SSI
-  if (hs->ssi != NULL) {
-    add_content_len = 0; /* @todo: get maximum file length from SSI */
-  } else
-#endif /* LWIP_HTTPD_SSI */
-  if ((hs->handle == NULL) ||
-      ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) {
-    add_content_len = 0;
-  }
-  if (add_content_len) {
-    size_t len;
-    lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
-      hs->handle->len);
-    len = strlen(hs->hdr_content_len);
-    if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) {
-      SMEMCPY(&hs->hdr_content_len[len], CRLF "\0", 3);
-      hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len;
-    } else {
-      add_content_len = 0;
-    }
-  }
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-  if (add_content_len) {
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN];
-  } else {
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
-  }
-#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-  if (add_content_len) {
-    hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
-  }
-#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-
-  /* Set up to send the first header string. */
-  hs->hdr_index = 0;
-  hs->hdr_pos = 0;
-}
-
-/** Sub-function of http_send(): send dynamic headers
- *
- * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued
- *           - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body
- *           - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending,
- *                                      so don't send HTTP body yet
- */
-static u8_t
-http_send_headers(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  err_t err;
-  u16_t len;
-  u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
-  u16_t hdrlen, sendlen;
-
-  /* How much data can we send? */
-  len = tcp_sndbuf(pcb);
-  sendlen = len;
-
-  while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) {
-    const void *ptr;
-    u16_t old_sendlen;
-    u8_t apiflags;
-    /* How much do we have to send from the current header? */
-    hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]);
-
-    /* How much of this can we send? */
-    sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos);
-
-    /* Send this amount of data or as much as we can given memory
-     * constraints. */
-    ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos);
-    old_sendlen = sendlen;
-    apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr);
-    if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) {
-      /* content-length is always volatile */
-      apiflags |= TCP_WRITE_FLAG_COPY;
-    }
-    if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) {
-      apiflags |= TCP_WRITE_FLAG_MORE;
-    }
-    err = http_write(pcb, ptr, &sendlen, apiflags);
-    if ((err == ERR_OK) && (old_sendlen != sendlen)) {
-      /* Remember that we added some more data to be transmitted. */
-      data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
-    } else if (err != ERR_OK) {
-       /* special case: http_write does not try to send 1 byte */
-      sendlen = 0;
-    }
-
-    /* Fix up the header position for the next time round. */
-    hs->hdr_pos += sendlen;
-    len -= sendlen;
-
-    /* Have we finished sending this string? */
-    if(hs->hdr_pos == hdrlen) {
-      /* Yes - move on to the next one */
-      hs->hdr_index++;
-      /* skip headers that are NULL (not all headers are required) */
-      while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) &&
-         (hs->hdrs[hs->hdr_index] == NULL)) {
-        hs->hdr_index++;
-      }
-      hs->hdr_pos = 0;
-    }
-  }
-
-  if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) {
-    /* When we are at the end of the headers, check for data to send
-     * instead of waiting for ACK from remote side to continue
-     * (which would happen when sending files from async read). */
-    if(http_check_eof(pcb, hs)) {
-      data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
-    }
-  }
-  /* If we get here and there are still header bytes to send, we send
-   * the header information we just wrote immediately. If there are no
-   * more headers to send, but we do have file data to send, drop through
-   * to try to send some file data too. */
-  if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n"));
-    return HTTP_DATA_TO_SEND_BREAK;
-  }
-  return data_to_send;
-}
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-
-/** Sub-function of http_send(): end-of-file (or block) is reached,
- * either close the file or read the next block (if supported).
- *
- * @returns: 0 if the file is finished or no data has been read
- *           1 if the file is not finished and data has been read
- */
-static u8_t
-http_check_eof(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  int bytes_left;
-#if LWIP_HTTPD_DYNAMIC_FILE_READ
-  int count;
-#ifdef HTTPD_MAX_WRITE_LEN
-  int max_write_len;
-#endif /* HTTPD_MAX_WRITE_LEN */
-#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
-
-  /* Do we have a valid file handle? */
-  if (hs->handle == NULL) {
-    /* No - close the connection. */
-    http_eof(pcb, hs);
-    return 0;
-  }
-  bytes_left = fs_bytes_left(hs->handle);
-  if (bytes_left <= 0) {
-    /* We reached the end of the file so this request is done. */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
-    http_eof(pcb, hs);
-    return 0;
-  }
-#if LWIP_HTTPD_DYNAMIC_FILE_READ
-  /* Do we already have a send buffer allocated? */
-  if(hs->buf) {
-    /* Yes - get the length of the buffer */
-    count = LWIP_MIN(hs->buf_len, bytes_left);
-  } else {
-    /* We don't have a send buffer so allocate one now */
-    count = tcp_sndbuf(pcb);
-    if(bytes_left < count) {
-      count = bytes_left;
-    }
-#ifdef HTTPD_MAX_WRITE_LEN
-    /* Additional limitation: e.g. don't enqueue more than 2*mss at once */
-    max_write_len = HTTPD_MAX_WRITE_LEN(pcb);
-    if (count > max_write_len) {
-      count = max_write_len;
-    }
-#endif /* HTTPD_MAX_WRITE_LEN */
-    do {
-      hs->buf = (char*)mem_malloc((mem_size_t)count);
-      if (hs->buf != NULL) {
-        hs->buf_len = count;
-        break;
-      }
-      count = count / 2;
-    } while (count > 100);
-
-    /* Did we get a send buffer? If not, return immediately. */
-    if (hs->buf == NULL) {
-      LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n"));
-      return 0;
-    }
-  }
-
-  /* Read a block of data from the file. */
-  LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count));
-
-#if LWIP_HTTPD_FS_ASYNC_READ
-  count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs);
-#else /* LWIP_HTTPD_FS_ASYNC_READ */
-  count = fs_read(hs->handle, hs->buf, count);
-#endif /* LWIP_HTTPD_FS_ASYNC_READ */
-  if (count < 0) {
-    if (count == FS_READ_DELAYED) {
-      /* Delayed read, wait for FS to unblock us */
-      return 0;
-    }
-    /* We reached the end of the file so this request is done.
-     * @todo: close here for HTTP/1.1 when reading file fails */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
-    http_eof(pcb, hs);
-    return 0;
-  }
-
-  /* Set up to send the block of data we just read */
-  LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count));
-  hs->left = count;
-  hs->file = hs->buf;
-#if LWIP_HTTPD_SSI
-  if (hs->ssi) {
-    hs->ssi->parse_left = count;
-    hs->ssi->parsed = hs->buf;
-  }
-#endif /* LWIP_HTTPD_SSI */
-#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */
-  LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0);
-#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */
-  return 1;
-}
-
-/** Sub-function of http_send(): This is the normal send-routine for non-ssi files
- *
- * @returns: - 1: data has been written (so call tcp_ouput)
- *           - 0: no data has been written (no need to call tcp_output)
- */
-static u8_t
-http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  err_t err;
-  u16_t len;
-  u8_t data_to_send = 0;
-
-  /* We are not processing an SHTML file so no tag checking is necessary.
-   * Just send the data as we received it from the file. */
-  len = (u16_t)LWIP_MIN(hs->left, 0xffff);
-
-  err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
-  if (err == ERR_OK) {
-    data_to_send = 1;
-    hs->file += len;
-    hs->left -= len;
-  }
-
-  return data_to_send;
-}
-
-#if LWIP_HTTPD_SSI
-/** Sub-function of http_send(): This is the send-routine for ssi files
- *
- * @returns: - 1: data has been written (so call tcp_ouput)
- *           - 0: no data has been written (no need to call tcp_output)
- */
-static u8_t
-http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  err_t err = ERR_OK;
-  u16_t len;
-  u8_t data_to_send = 0;
-
-  struct http_ssi_state *ssi = hs->ssi;
-  LWIP_ASSERT("ssi != NULL", ssi != NULL);
-  /* We are processing an SHTML file so need to scan for tags and replace
-   * them with insert strings. We need to be careful here since a tag may
-   * straddle the boundary of two blocks read from the file and we may also
-   * have to split the insert string between two tcp_write operations. */
-
-  /* How much data could we send? */
-  len = tcp_sndbuf(pcb);
-
-  /* Do we have remaining data to send before parsing more? */
-  if(ssi->parsed > hs->file) {
-    len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff);
-
-    err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
-    if (err == ERR_OK) {
-      data_to_send = 1;
-      hs->file += len;
-      hs->left -= len;
-    }
-
-    /* If the send buffer is full, return now. */
-    if(tcp_sndbuf(pcb) == 0) {
-      return data_to_send;
-    }
-  }
-
-  LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left));
-
-  /* We have sent all the data that was already parsed so continue parsing
-   * the buffer contents looking for SSI tags. */
-  while((ssi->parse_left) && (err == ERR_OK)) {
-    if (len == 0) {
-      return data_to_send;
-    }
-    switch(ssi->tag_state) {
-      case TAG_NONE:
-        /* We are not currently processing an SSI tag so scan for the
-         * start of the lead-in marker. */
-        if(*ssi->parsed == g_pcTagLeadIn[0]) {
-          /* We found what could be the lead-in for a new tag so change
-           * state appropriately. */
-          ssi->tag_state = TAG_LEADIN;
-          ssi->tag_index = 1;
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-          ssi->tag_started = ssi->parsed;
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */
-        }
-
-        /* Move on to the next character in the buffer */
-        ssi->parse_left--;
-        ssi->parsed++;
-        break;
-
-      case TAG_LEADIN:
-        /* We are processing the lead-in marker, looking for the start of
-         * the tag name. */
-
-        /* Have we reached the end of the leadin? */
-        if(ssi->tag_index == LEN_TAG_LEAD_IN) {
-          ssi->tag_index = 0;
-          ssi->tag_state = TAG_FOUND;
-        } else {
-          /* Have we found the next character we expect for the tag leadin? */
-          if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) {
-            /* Yes - move to the next one unless we have found the complete
-             * leadin, in which case we start looking for the tag itself */
-            ssi->tag_index++;
-          } else {
-            /* We found an unexpected character so this is not a tag. Move
-             * back to idle state. */
-            ssi->tag_state = TAG_NONE;
-          }
-
-          /* Move on to the next character in the buffer */
-          ssi->parse_left--;
-          ssi->parsed++;
-        }
-        break;
-
-      case TAG_FOUND:
-        /* We are reading the tag name, looking for the start of the
-         * lead-out marker and removing any whitespace found. */
-
-        /* Remove leading whitespace between the tag leading and the first
-         * tag name character. */
-        if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') ||
-           (*ssi->parsed == '\t') || (*ssi->parsed == '\n') ||
-           (*ssi->parsed == '\r'))) {
-          /* Move on to the next character in the buffer */
-          ssi->parse_left--;
-          ssi->parsed++;
-          break;
-        }
-
-        /* Have we found the end of the tag name? This is signalled by
-         * us finding the first leadout character or whitespace */
-        if((*ssi->parsed == g_pcTagLeadOut[0]) ||
-           (*ssi->parsed == ' ')  || (*ssi->parsed == '\t') ||
-           (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) {
-
-          if(ssi->tag_index == 0) {
-            /* We read a zero length tag so ignore it. */
-            ssi->tag_state = TAG_NONE;
-          } else {
-            /* We read a non-empty tag so go ahead and look for the
-             * leadout string. */
-            ssi->tag_state = TAG_LEADOUT;
-            LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff);
-            ssi->tag_name_len = (u8_t)ssi->tag_index;
-            ssi->tag_name[ssi->tag_index] = '\0';
-            if(*ssi->parsed == g_pcTagLeadOut[0]) {
-              ssi->tag_index = 1;
-            } else {
-              ssi->tag_index = 0;
-            }
-          }
-        } else {
-          /* This character is part of the tag name so save it */
-          if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) {
-            ssi->tag_name[ssi->tag_index++] = *ssi->parsed;
-          } else {
-            /* The tag was too long so ignore it. */
-            ssi->tag_state = TAG_NONE;
-          }
-        }
-
-        /* Move on to the next character in the buffer */
-        ssi->parse_left--;
-        ssi->parsed++;
-
-        break;
-
-      /* We are looking for the end of the lead-out marker. */
-      case TAG_LEADOUT:
-        /* Remove leading whitespace between the tag leading and the first
-         * tag leadout character. */
-        if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') ||
-           (*ssi->parsed == '\t') || (*ssi->parsed == '\n') ||
-           (*ssi->parsed == '\r'))) {
-          /* Move on to the next character in the buffer */
-          ssi->parse_left--;
-          ssi->parsed++;
-          break;
-        }
-
-        /* Have we found the next character we expect for the tag leadout? */
-        if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) {
-          /* Yes - move to the next one unless we have found the complete
-           * leadout, in which case we need to call the client to process
-           * the tag. */
-
-          /* Move on to the next character in the buffer */
-          ssi->parse_left--;
-          ssi->parsed++;
-
-          if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) {
-            /* Call the client to ask for the insert string for the
-             * tag we just found. */
-#if LWIP_HTTPD_SSI_MULTIPART
-            ssi->tag_part = 0; /* start with tag part 0 */
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-            get_tag_insert(hs);
-
-            /* Next time through, we are going to be sending data
-             * immediately, either the end of the block we start
-             * sending here or the insert string. */
-            ssi->tag_index = 0;
-            ssi->tag_state = TAG_SENDING;
-            ssi->tag_end = ssi->parsed;
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-            ssi->parsed = ssi->tag_started;
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
-
-            /* If there is any unsent data in the buffer prior to the
-             * tag, we need to send it now. */
-            if (ssi->tag_end > hs->file) {
-              /* How much of the data can we send? */
-#if LWIP_HTTPD_SSI_INCLUDE_TAG
-              len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff);
-#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
-              /* we would include the tag in sending */
-              len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff);
-#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
-
-              err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
-              if (err == ERR_OK) {
-                data_to_send = 1;
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-                if(ssi->tag_started <= hs->file) {
-                  /* pretend to have sent the tag, too */
-                  len += ssi->tag_end - ssi->tag_started;
-                }
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
-                hs->file += len;
-                hs->left -= len;
-              }
-            }
-          } else {
-            ssi->tag_index++;
-          }
-        } else {
-          /* We found an unexpected character so this is not a tag. Move
-           * back to idle state. */
-          ssi->parse_left--;
-          ssi->parsed++;
-          ssi->tag_state = TAG_NONE;
-        }
-        break;
-
-      /*
-       * We have found a valid tag and are in the process of sending
-       * data as a result of that discovery. We send either remaining data
-       * from the file prior to the insert point or the insert string itself.
-       */
-      case TAG_SENDING:
-        /* Do we have any remaining file data to send from the buffer prior
-         * to the tag? */
-        if(ssi->tag_end > hs->file) {
-          /* How much of the data can we send? */
-#if LWIP_HTTPD_SSI_INCLUDE_TAG
-          len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff);
-#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
-          LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file);
-          /* we would include the tag in sending */
-          len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff);
-#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
-          if (len != 0) {
-            err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
-          } else {
-            err = ERR_OK;
-          }
-          if (err == ERR_OK) {
-            data_to_send = 1;
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-            if(ssi->tag_started <= hs->file) {
-              /* pretend to have sent the tag, too */
-              len += ssi->tag_end - ssi->tag_started;
-            }
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
-            hs->file += len;
-            hs->left -= len;
-          }
-        } else {
-#if LWIP_HTTPD_SSI_MULTIPART
-          if(ssi->tag_index >= ssi->tag_insert_len) {
-            /* Did the last SSIHandler have more to send? */
-            if (ssi->tag_part != HTTPD_LAST_TAG_PART) {
-              /* If so, call it again */
-              ssi->tag_index = 0;
-              get_tag_insert(hs);
-            }
-          }
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-
-          /* Do we still have insert data left to send? */
-          if(ssi->tag_index < ssi->tag_insert_len) {
-            /* We are sending the insert string itself. How much of the
-             * insert can we send? */
-            len = (ssi->tag_insert_len - ssi->tag_index);
-
-            /* Note that we set the copy flag here since we only have a
-             * single tag insert buffer per connection. If we don't do
-             * this, insert corruption can occur if more than one insert
-             * is processed before we call tcp_output. */
-            err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len,
-                             HTTP_IS_TAG_VOLATILE(hs));
-            if (err == ERR_OK) {
-              data_to_send = 1;
-              ssi->tag_index += len;
-              /* Don't return here: keep on sending data */
-            }
-          } else {
-#if LWIP_HTTPD_SSI_MULTIPART
-            if (ssi->tag_part == HTTPD_LAST_TAG_PART)
-#endif /* LWIP_HTTPD_SSI_MULTIPART */
-            {
-              /* We have sent all the insert data so go back to looking for
-               * a new tag. */
-              LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n"));
-              ssi->tag_index = 0;
-              ssi->tag_state = TAG_NONE;
-#if !LWIP_HTTPD_SSI_INCLUDE_TAG
-              ssi->parsed = ssi->tag_end;
-#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
-            }
-          }
-          break;
-        default:
-          break;
-      }
-    }
-  }
-
-  /* If we drop out of the end of the for loop, this implies we must have
-   * file data to send so send it now. In TAG_SENDING state, we've already
-   * handled this so skip the send if that's the case. */
-  if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) {
-    len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff);
-
-    err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
-    if (err == ERR_OK) {
-      data_to_send = 1;
-      hs->file += len;
-      hs->left -= len;
-    }
-  }
-  return data_to_send;
-}
-#endif /* LWIP_HTTPD_SSI */
-
-/**
- * Try to send more data on this pcb.
- *
- * @param pcb the pcb to send data
- * @param hs connection state
- */
-static u8_t
-http_send(struct tcp_pcb *pcb, struct http_state *hs)
-{
-  u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
-
-  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb,
-    (void*)hs, hs != NULL ? (int)hs->left : 0));
-
-#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
-  if (hs->unrecved_bytes != 0) {
-    return 0;
-  }
-#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
-
-  /* If we were passed a NULL state structure pointer, ignore the call. */
-  if (hs == NULL) {
-    return 0;
-  }
-
-#if LWIP_HTTPD_FS_ASYNC_READ
-  /* Check if we are allowed to read from this file.
-     (e.g. SSI might want to delay sending until data is available) */
-  if (!fs_is_file_ready(hs->handle, http_continue, hs)) {
-    return 0;
-  }
-#endif /* LWIP_HTTPD_FS_ASYNC_READ */
-
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-  /* Do we have any more header data to send for this file? */
-  if (hs->hdr_index < NUM_FILE_HDR_STRINGS) {
-    data_to_send = http_send_headers(pcb, hs);
-    if ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) &&
-        (hs->hdr_index < NUM_FILE_HDR_STRINGS)) {
-      return data_to_send;
-    }
-  }
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-
-  /* Have we run out of file data to send? If so, we need to read the next
-   * block from the file. */
-  if (hs->left == 0) {
-    if (!http_check_eof(pcb, hs)) {
-      return 0;
-    }
-  }
-
-#if LWIP_HTTPD_SSI
-  if(hs->ssi) {
-    data_to_send = http_send_data_ssi(pcb, hs);
-  } else
-#endif /* LWIP_HTTPD_SSI */
-  {
-    data_to_send = http_send_data_nonssi(pcb, hs);
-  }
-
-  if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) {
-    /* We reached the end of the file so this request is done.
-     * This adds the FIN flag right into the last data segment. */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
-    http_eof(pcb, hs);
-    return 0;
-  }
-  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n"));
-  return data_to_send;
-}
-
-#if LWIP_HTTPD_SUPPORT_EXTSTATUS
-/** Initialize a http connection with a file to send for an error message
- *
- * @param hs http connection state
- * @param error_nr HTTP error number
- * @return ERR_OK if file was found and hs has been initialized correctly
- *         another err_t otherwise
- */
-static err_t
-http_find_error_file(struct http_state *hs, u16_t error_nr)
-{
-  const char *uri1, *uri2, *uri3;
-  err_t err;
-
-  if (error_nr == 501) {
-    uri1 = "/501.html";
-    uri2 = "/501.htm";
-    uri3 = "/501.shtml";
-  } else {
-    /* 400 (bad request is the default) */
-    uri1 = "/400.html";
-    uri2 = "/400.htm";
-    uri3 = "/400.shtml";
-  }
-  err = fs_open(&hs->file_handle, uri1);
-  if (err != ERR_OK) {
-    err = fs_open(&hs->file_handle, uri2);
-    if (err != ERR_OK) {
-      err = fs_open(&hs->file_handle, uri3);
-      if (err != ERR_OK) {
-        LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n",
-          error_nr));
-        return ERR_ARG;
-      }
-    }
-  }
-  return http_init_file(hs, &hs->file_handle, 0, NULL, 0, NULL);
-}
-#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
-#define http_find_error_file(hs, error_nr) ERR_ARG
-#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
-
-/**
- * Get the file struct for a 404 error page.
- * Tries some file names and returns NULL if none found.
- *
- * @param uri pointer that receives the actual file name URI
- * @return file struct for the error page or NULL no matching file was found
- */
-static struct fs_file *
-http_get_404_file(struct http_state *hs, const char **uri)
-{
-  err_t err;
-
-  *uri = "/404.html";
-  err = fs_open(&hs->file_handle, *uri);
-  if (err != ERR_OK) {
-    /* 404.html doesn't exist. Try 404.htm instead. */
-    *uri = "/404.htm";
-    err = fs_open(&hs->file_handle, *uri);
-    if (err != ERR_OK) {
-      /* 404.htm doesn't exist either. Try 404.shtml instead. */
-      *uri = "/404.shtml";
-      err = fs_open(&hs->file_handle, *uri);
-      if (err != ERR_OK) {
-        /* 404.htm doesn't exist either. Indicate to the caller that it should
-         * send back a default 404 page.
-         */
-        *uri = NULL;
-        return NULL;
-      }
-    }
-  }
-
-  return &hs->file_handle;
-}
-
-#if LWIP_HTTPD_SUPPORT_POST
-static err_t
-http_handle_post_finished(struct http_state *hs)
-{
-#if LWIP_HTTPD_POST_MANUAL_WND
-  /* Prevent multiple calls to httpd_post_finished, since it might have already
-     been called before from httpd_post_data_recved(). */
-  if (hs->post_finished) {
-    return ERR_OK;
-  }
-  hs->post_finished = 1;
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-  /* application error or POST finished */
-  /* NULL-terminate the buffer */
-  http_uri_buf[0] = 0;
-  httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN);
-  return http_find_file(hs, http_uri_buf, 0);
-}
-
-/** Pass received POST body data to the application and correctly handle
- * returning a response document or closing the connection.
- * ATTENTION: The application is responsible for the pbuf now, so don't free it!
- *
- * @param hs http connection state
- * @param p pbuf to pass to the application
- * @return ERR_OK if passed successfully, another err_t if the response file
- *         hasn't been found (after POST finished)
- */
-static err_t
-http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
-{
-  err_t err;
-
-  if (p != NULL) {
-    /* adjust remaining Content-Length */
-    if (hs->post_content_len_left < p->tot_len) {
-      hs->post_content_len_left = 0;
-    } else {
-      hs->post_content_len_left -= p->tot_len;
-    }
-  }
-  err = httpd_post_receive_data(hs, p);
-  if (err != ERR_OK) {
-    /* Ignore remaining content in case of application error */
-    hs->post_content_len_left = 0;
-  }
-  if (hs->post_content_len_left == 0) {
-#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
-    if (hs->unrecved_bytes != 0) {
-       return ERR_OK;
-    }
-#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
-    /* application error or POST finished */
-    return http_handle_post_finished(hs);
-  }
-
-  return ERR_OK;
-}
-
-/** Handle a post request. Called from http_parse_request when method 'POST'
- * is found.
- *
- * @param p The input pbuf (containing the POST header and body).
- * @param hs The http connection state.
- * @param data HTTP request (header and part of body) from input pbuf(s).
- * @param data_len Size of 'data'.
- * @param uri The HTTP URI parsed from input pbuf(s).
- * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP
- *                header starts).
- * @return ERR_OK: POST correctly parsed and accepted by the application.
- *         ERR_INPROGRESS: POST not completely parsed (no error yet)
- *         another err_t: Error parsing POST or denied by the application
- */
-static err_t
-http_post_request(struct pbuf *inp, struct http_state *hs,
-                  char *data, u16_t data_len, char *uri, char *uri_end)
-{
-  err_t err;
-  /* search for end-of-header (first double-CRLF) */
-  char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
-
-  if (crlfcrlf != NULL) {
-    /* search for "Content-Length: " */
-#define HTTP_HDR_CONTENT_LEN                "Content-Length: "
-#define HTTP_HDR_CONTENT_LEN_LEN            16
-#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN  10
-    char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
-    if (scontent_len != NULL) {
-      char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
-      if (scontent_len_end != NULL) {
-        int content_len;
-        char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
-        content_len = atoi(content_len_num);
-        if (content_len == 0) {
-          /* if atoi returns 0 on error, fix this */
-          if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) {
-            content_len = -1;
-          }
-        }
-        if (content_len >= 0) {
-          /* adjust length of HTTP header passed to application */
-          const char *hdr_start_after_uri = uri_end + 1;
-          u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data);
-          u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
-          u8_t post_auto_wnd = 1;
-          http_uri_buf[0] = 0;
-          /* trim http header */
-          *crlfcrlf = 0;
-          err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len,
-            http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd);
-          if (err == ERR_OK) {
-            /* try to pass in data of the first pbuf(s) */
-            struct pbuf *q = inp;
-            u16_t start_offset = hdr_len;
-#if LWIP_HTTPD_POST_MANUAL_WND
-            hs->no_auto_wnd = !post_auto_wnd;
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-            /* set the Content-Length to be received for this POST */
-            hs->post_content_len_left = (u32_t)content_len;
-
-            /* get to the pbuf where the body starts */
-            while((q != NULL) && (q->len <= start_offset)) {
-              start_offset -= q->len;
-              q = q->next;
-            }
-            if (q != NULL) {
-              /* hide the remaining HTTP header */
-              pbuf_header(q, -(s16_t)start_offset);
-#if LWIP_HTTPD_POST_MANUAL_WND
-              if (!post_auto_wnd) {
-                /* already tcp_recved() this data... */
-                hs->unrecved_bytes = q->tot_len;
-              }
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-              pbuf_ref(q);
-              return http_post_rxpbuf(hs, q);
-            } else if (hs->post_content_len_left == 0) {
-              q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
-              return http_post_rxpbuf(hs, q);
-            } else {
-              return ERR_OK;
-            }
-          } else {
-            /* return file passed from application */
-            return http_find_file(hs, http_uri_buf, 0);
-          }
-        } else {
-          LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n",
-            content_len_num));
-          return ERR_ARG;
-        }
-      }
-    }
-    /* If we come here, headers are fully received (double-crlf), but Content-Length
-       was not included. Since this is currently the only supported method, we have
-       to fail in this case! */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n"));
-    return ERR_ARG;
-  }
-  /* if we come here, the POST is incomplete */
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-  return ERR_INPROGRESS;
-#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-  return ERR_ARG;
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-}
-
-#if LWIP_HTTPD_POST_MANUAL_WND
-/** A POST implementation can call this function to update the TCP window.
- * This can be used to throttle data reception (e.g. when received data is
- * programmed to flash and data is received faster than programmed).
- *
- * @param connection A connection handle passed to httpd_post_begin for which
- *        httpd_post_finished has *NOT* been called yet!
- * @param recved_len Length of data received (for window update)
- */
-void httpd_post_data_recved(void *connection, u16_t recved_len)
-{
-  struct http_state *hs = (struct http_state*)connection;
-  if (hs != NULL) {
-    if (hs->no_auto_wnd) {
-      u16_t len = recved_len;
-      if (hs->unrecved_bytes >= recved_len) {
-        hs->unrecved_bytes -= recved_len;
-      } else {
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n"));
-        len = (u16_t)hs->unrecved_bytes;
-        hs->unrecved_bytes = 0;
-      }
-      if (hs->pcb != NULL) {
-        if (len != 0) {
-          tcp_recved(hs->pcb, len);
-        }
-        if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) {
-          /* finished handling POST */
-          http_handle_post_finished(hs);
-          http_send(hs->pcb, hs);
-        }
-      }
-    }
-  }
-}
-#endif /* LWIP_HTTPD_POST_MANUAL_WND */
-
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-
-#if LWIP_HTTPD_FS_ASYNC_READ
-/** Try to send more data if file has been blocked before
- * This is a callback function passed to fs_read_async().
- */
-static void
-http_continue(void *connection)
-{
-  struct http_state *hs = (struct http_state*)connection;
-  if (hs && (hs->pcb) && (hs->handle)) {
-    LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL);
-    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n"));
-    if (http_send(hs->pcb, hs)) {
-      /* If we wrote anything to be sent, go ahead and send it now. */
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n"));
-      tcp_output(hs->pcb);
-    }
-  }
-}
-#endif /* LWIP_HTTPD_FS_ASYNC_READ */
-
-/**
- * When data has been received in the correct state, try to parse it
- * as a HTTP request.
- *
- * @param inp the received pbuf
- * @param hs the connection state
- * @param pcb the tcp_pcb which received this packet
- * @return ERR_OK if request was OK and hs has been initialized correctly
- *         ERR_INPROGRESS if request was OK so far but not fully received
- *         another err_t otherwise
- */
-static err_t
-http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
-{
-  char *data;
-  char *crlf;
-  u16_t data_len;
-  struct pbuf *p = inp;
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-  u16_t clen;
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-#if LWIP_HTTPD_SUPPORT_POST
-  err_t err;
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-
-  LWIP_UNUSED_ARG(pcb); /* only used for post */
-  LWIP_ASSERT("p != NULL", p != NULL);
-  LWIP_ASSERT("hs != NULL", hs != NULL);
-
-  if ((hs->handle != NULL) || (hs->file != NULL)) {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n"));
-    /* already sending a file */
-    /* @todo: abort? */
-    return ERR_USE;
-  }
-
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-
-  LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len));
-
-  /* first check allowed characters in this pbuf? */
-
-  /* enqueue the pbuf */
-  if (hs->req == NULL) {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n"));
-    hs->req = p;
-  } else {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n"));
-    pbuf_cat(hs->req, p);
-  }
-  /* increase pbuf ref counter as it is freed when we return but we want to
-     keep it on the req list */
-  pbuf_ref(p);
-
-  if (hs->req->next != NULL) {
-    data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH);
-    pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0);
-    data = httpd_req_buf;
-  } else
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-  {
-    data = (char *)p->payload;
-    data_len = p->len;
-    if (p->len != p->tot_len) {
-      LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n"));
-    }
-  }
-
-  /* received enough data for minimal request? */
-  if (data_len >= MIN_REQ_LEN) {
-    /* wait for CRLF before parsing anything */
-    crlf = lwip_strnstr(data, CRLF, data_len);
-    if (crlf != NULL) {
-#if LWIP_HTTPD_SUPPORT_POST
-      int is_post = 0;
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-      int is_09 = 0;
-      char *sp1, *sp2;
-      u16_t left_len, uri_len;
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n"));
-      /* parse method */
-      if (!strncmp(data, "GET ", 4)) {
-        sp1 = data + 3;
-        /* received GET request */
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n"));
-#if LWIP_HTTPD_SUPPORT_POST
-      } else if (!strncmp(data, "POST ", 5)) {
-        /* store request type */
-        is_post = 1;
-        sp1 = data + 4;
-        /* received GET request */
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n"));
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-      } else {
-        /* null-terminate the METHOD (pbuf is freed anyway wen returning) */
-        data[4] = 0;
-        /* unsupported method! */
-        LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n",
-          data));
-        return http_find_error_file(hs, 501);
-      }
-      /* if we come here, method is OK, parse URI */
-      left_len = (u16_t)(data_len - ((sp1 +1) - data));
-      sp2 = lwip_strnstr(sp1 + 1, " ", left_len);
-#if LWIP_HTTPD_SUPPORT_V09
-      if (sp2 == NULL) {
-        /* HTTP 0.9: respond with correct protocol version */
-        sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len);
-        is_09 = 1;
-#if LWIP_HTTPD_SUPPORT_POST
-        if (is_post) {
-          /* HTTP/0.9 does not support POST */
-          goto badrequest;
-        }
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-      }
-#endif /* LWIP_HTTPD_SUPPORT_V09 */
-      uri_len = (u16_t)(sp2 - (sp1 + 1));
-      if ((sp2 != 0) && (sp2 > sp1)) {
-        /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */
-        if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) {
-          char *uri = sp1 + 1;
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-          /* This is HTTP/1.0 compatible: for strict 1.1, a connection
-             would always be persistent unless "close" was specified. */
-          if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
-              lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
-            hs->keepalive = 1;
-          } else {
-            hs->keepalive = 0;
-          }
-#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-          /* null-terminate the METHOD (pbuf is freed anyway wen returning) */
-          *sp1 = 0;
-          uri[uri_len] = 0;
-          LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n",
-                      data, uri));
-#if LWIP_HTTPD_SUPPORT_POST
-          if (is_post) {
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-            struct pbuf *q = hs->req;
-#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-            struct pbuf *q = inp;
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-            err = http_post_request(q, hs, data, data_len, uri, sp2);
-            if (err != ERR_OK) {
-              /* restore header for next try */
-              *sp1 = ' ';
-              *sp2 = ' ';
-              uri[uri_len] = ' ';
-            }
-            if (err == ERR_ARG) {
-              goto badrequest;
-            }
-            return err;
-          } else
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-          {
-            return http_find_file(hs, uri, is_09);
-          }
-        }
-      } else {
-        LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n"));
-      }
-    }
-  }
-
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-  clen = pbuf_clen(hs->req);
-  if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) &&
-    (clen <= LWIP_HTTPD_REQ_QUEUELEN)) {
-    /* request not fully received (too short or CRLF is missing) */
-    return ERR_INPROGRESS;
-  } else
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-  {
-#if LWIP_HTTPD_SUPPORT_POST
-badrequest:
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n"));
-    /* could not parse request */
-    return http_find_error_file(hs, 400);
-  }
-}
-
-/** Try to find the file specified by uri and, if found, initialize hs
- * accordingly.
- *
- * @param hs the connection state
- * @param uri the HTTP header URI
- * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
- * @return ERR_OK if file was found and hs has been initialized correctly
- *         another err_t otherwise
- */
-static err_t
-http_find_file(struct http_state *hs, const char *uri, int is_09)
-{
-  size_t loop;
-  struct fs_file *file = NULL;
-  char *params = NULL;
-  err_t err;
-#if LWIP_HTTPD_CGI
-  int i;
-#endif /* LWIP_HTTPD_CGI */
-#if !LWIP_HTTPD_SSI
-  const
-#endif /* !LWIP_HTTPD_SSI */
-  /* By default, assume we will not be processing server-side-includes tags */
-  u8_t tag_check = 0;
-
-  /* Have we been asked for the default file (in root or a directory) ? */
-#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
-  size_t uri_len = strlen(uri);
-  if ((uri_len > 0) && (uri[uri_len-1] == '/') &&
-      ((uri != http_uri_buf) || (uri_len == 1))) {
-    size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1);
-    if (copy_len > 0) {
-      MEMCPY(http_uri_buf, uri, copy_len);
-      http_uri_buf[copy_len] = 0;
-    }
-#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
-  if ((uri[0] == '/') &&  (uri[1] == 0)) {
-#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
-    /* Try each of the configured default filenames until we find one
-       that exists. */
-    for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
-      const char* file_name;
-#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
-      if (copy_len > 0) {
-        size_t len_left = sizeof(http_uri_buf) - copy_len - 1;
-        if (len_left > 0) {
-          size_t name_len = strlen(g_psDefaultFilenames[loop].name);
-          size_t name_copy_len = LWIP_MIN(len_left, name_len);
-          MEMCPY(&http_uri_buf[copy_len], g_psDefaultFilenames[loop].name, name_copy_len);
-        }
-        file_name = http_uri_buf;
-      } else
-#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
-      {
-        file_name = g_psDefaultFilenames[loop].name;
-      }
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name));
-      err = fs_open(&hs->file_handle, file_name);
-      if(err == ERR_OK) {
-        uri = file_name;
-        file = &hs->file_handle;
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n"));
-#if LWIP_HTTPD_SSI
-        tag_check = g_psDefaultFilenames[loop].shtml;
-#endif /* LWIP_HTTPD_SSI */
-        break;
-      }
-    }
-  }
-  if (file == NULL) {
-    /* No - we've been asked for a specific file. */
-    /* First, isolate the base URI (without any parameters) */
-    params = (char *)strchr(uri, '?');
-    if (params != NULL) {
-      /* URI contains parameters. NULL-terminate the base URI */
-      *params = '\0';
-      params++;
-    }
-
-#if LWIP_HTTPD_CGI
-    http_cgi_paramcount = -1;
-    /* Does the base URI we have isolated correspond to a CGI handler? */
-    if (g_iNumCGIs && g_pCGIs) {
-      for (i = 0; i < g_iNumCGIs; i++) {
-        if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) {
-          /*
-           * We found a CGI that handles this URI so extract the
-           * parameters and call the handler.
-           */
-           http_cgi_paramcount = extract_uri_parameters(hs, params);
-           uri = g_pCGIs[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params,
-                                          hs->param_vals);
-           break;
-        }
-      }
-    }
-#endif /* LWIP_HTTPD_CGI */
-
-    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri));
-
-    err = fs_open(&hs->file_handle, uri);
-    if (err == ERR_OK) {
-       file = &hs->file_handle;
-    } else {
-      file = http_get_404_file(hs, &uri);
-    }
-#if LWIP_HTTPD_SSI
-    if (file != NULL) {
-      /* See if we have been asked for an shtml file and, if so,
-         enable tag checking. */
-      const char* ext = NULL, *sub;
-      char* param = (char*)strstr(uri, "?");
-      if (param != NULL) {
-         /* separate uri from parameters for now, set back later */
-         *param = 0;
-      }
-      sub = uri;
-      ext = uri;
-      for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, "."))
-      {
-         ext = sub;
-         sub++;
-      }
-      tag_check = 0;
-      for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
-        if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) {
-          tag_check = 1;
-          break;
-        }
-      }
-      if (param != NULL) {
-         *param = '?';
-      }
-    }
-#endif /* LWIP_HTTPD_SSI */
-  }
-  if (file == NULL) {
-    /* None of the default filenames exist so send back a 404 page */
-    file = http_get_404_file(hs, &uri);
-  }
-  return http_init_file(hs, file, is_09, uri, tag_check, params);
-}
-
-/** Initialize a http connection with a file to send (if found).
- * Called by http_find_file and http_find_error_file.
- *
- * @param hs http connection state
- * @param file file structure to send (or NULL if not found)
- * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
- * @param uri the HTTP header URI
- * @param tag_check enable SSI tag checking
- * @param params != NULL if URI has parameters (separated by '?')
- * @return ERR_OK if file was found and hs has been initialized correctly
- *         another err_t otherwise
- */
-static err_t
-http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri,
-               u8_t tag_check, char* params)
-{
-  if (file != NULL) {
-    /* file opened, initialise struct http_state */
-#if LWIP_HTTPD_SSI
-    if (tag_check) {
-      struct http_ssi_state *ssi = http_ssi_state_alloc();
-      if (ssi != NULL) {
-        ssi->tag_index = 0;
-        ssi->tag_state = TAG_NONE;
-        ssi->parsed = file->data;
-        ssi->parse_left = file->len;
-        ssi->tag_end = file->data;
-        hs->ssi = ssi;
-      }
-    }
-#else /* LWIP_HTTPD_SSI */
-    LWIP_UNUSED_ARG(tag_check);
-#endif /* LWIP_HTTPD_SSI */
-    hs->handle = file;
-    hs->file = file->data;
-    LWIP_ASSERT("File length must be positive!", (file->len >= 0));
-#if LWIP_HTTPD_CUSTOM_FILES
-    if (file->is_custom_file && (file->data == NULL)) {
-      /* custom file, need to read data first (via fs_read_custom) */
-      hs->left = 0;
-    } else
-#endif /* LWIP_HTTPD_CUSTOM_FILES */
-    {
-      hs->left = file->len;
-    }
-    hs->retries = 0;
-#if LWIP_HTTPD_TIMING
-    hs->time_started = sys_now();
-#endif /* LWIP_HTTPD_TIMING */
-#if !LWIP_HTTPD_DYNAMIC_HEADERS
-    LWIP_ASSERT("HTTP headers not included in file system",
-       (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0);
-#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */
-#if LWIP_HTTPD_SUPPORT_V09
-    if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) {
-      /* HTTP/0.9 responses are sent without HTTP header,
-         search for the end of the header. */
-      char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left);
-      if (file_start != NULL) {
-        size_t diff = file_start + 4 - hs->file;
-        hs->file += diff;
-        hs->left -= (u32_t)diff;
-      }
-    }
-#endif /* LWIP_HTTPD_SUPPORT_V09*/
-#if LWIP_HTTPD_CGI_SSI
-    if (params != NULL) {
-      /* URI contains parameters, call generic CGI handler */
-      int count;
-#if LWIP_HTTPD_CGI
-      if (http_cgi_paramcount >= 0) {
-        count = http_cgi_paramcount;
-      } else
-#endif
-      {
-        count = extract_uri_parameters(hs, params);
-      }
-      httpd_cgi_handler(uri, count, http_cgi_params, http_cgi_param_vals
-#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
-         , hs->handle->state
-#endif /* LWIP_HTTPD_FILE_STATE */
-                        );
-    }
-#else /* LWIP_HTTPD_CGI_SSI */
-    LWIP_UNUSED_ARG(params);
-#endif /* LWIP_HTTPD_CGI_SSI */
-  } else {
-    hs->handle = NULL;
-    hs->file = NULL;
-    hs->left = 0;
-    hs->retries = 0;
-  }
-#if LWIP_HTTPD_DYNAMIC_HEADERS
-  /* Determine the HTTP headers to send based on the file extension of
-   * the requested URI. */
-  if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) {
-    get_http_headers(hs, uri);
-  }
-#else /* LWIP_HTTPD_DYNAMIC_HEADERS */
-  LWIP_UNUSED_ARG(uri);
-#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
-#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
-  if (hs->keepalive) {
-#if LWIP_HTTPD_SSI
-     if (hs->ssi != NULL) {
-       hs->keepalive = 0;
-     } else
-#endif /* LWIP_HTTPD_SSI */
-     {
-       if ((hs->handle != NULL) &&
-           ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) {
-         hs->keepalive = 0;
-       }
-     }
-  }
-#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
-  return ERR_OK;
-}
-
-/**
- * The pcb had an error and is already deallocated.
- * The argument might still be valid (if != NULL).
- */
-static void
-http_err(void *arg, err_t err)
-{
-  struct http_state *hs = (struct http_state *)arg;
-  LWIP_UNUSED_ARG(err);
-
-  LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err)));
-
-  if (hs != NULL) {
-    http_state_free(hs);
-  }
-}
-
-/**
- * Data has been sent and acknowledged by the remote host.
- * This means that more data can be sent.
- */
-static err_t
-http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
-{
-  struct http_state *hs = (struct http_state *)arg;
-
-  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb));
-
-  LWIP_UNUSED_ARG(len);
-
-  if (hs == NULL) {
-    return ERR_OK;
-  }
-
-  hs->retries = 0;
-
-  http_send(pcb, hs);
-
-  return ERR_OK;
-}
-
-/**
- * The poll function is called every 2nd second.
- * If there has been no data sent (which resets the retries) in 8 seconds, close.
- * If the last portion of a file has not been sent in 2 seconds, close.
- *
- * This could be increased, but we don't want to waste resources for bad connections.
- */
-static err_t
-http_poll(void *arg, struct tcp_pcb *pcb)
-{
-  struct http_state *hs = (struct http_state *)arg;
-  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n",
-    (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state)));
-
-  if (hs == NULL) {
-    err_t closed;
-    /* arg is null, close. */
-    LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n"));
-    closed = http_close_conn(pcb, NULL);
-    LWIP_UNUSED_ARG(closed);
-#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR
-    if (closed == ERR_MEM) {
-       tcp_abort(pcb);
-       return ERR_ABRT;
-    }
-#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */
-    return ERR_OK;
-  } else {
-    hs->retries++;
-    if (hs->retries == HTTPD_MAX_RETRIES) {
-      LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n"));
-      http_close_conn(pcb, hs);
-      return ERR_OK;
-    }
-
-    /* If this connection has a file open, try to send some more data. If
-     * it has not yet received a GET request, don't do this since it will
-     * cause the connection to close immediately. */
-    if(hs && (hs->handle)) {
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n"));
-      if(http_send(pcb, hs)) {
-        /* If we wrote anything to be sent, go ahead and send it now. */
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n"));
-        tcp_output(pcb);
-      }
-    }
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Data has been received on this pcb.
- * For HTTP 1.0, this should normally only happen once (if the request fits in one packet).
- */
-static err_t
-http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
-{
-  struct http_state *hs = (struct http_state *)arg;
-  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb,
-    (void*)p, lwip_strerr(err)));
-
-  if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) {
-    /* error or closed by other side? */
-    if (p != NULL) {
-      /* Inform TCP that we have taken the data. */
-      tcp_recved(pcb, p->tot_len);
-      pbuf_free(p);
-    }
-    if (hs == NULL) {
-      /* this should not happen, only to be robust */
-      LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n"));
-    }
-    http_close_conn(pcb, hs);
-    return ERR_OK;
-  }
-
-#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
-  if (hs->no_auto_wnd) {
-     hs->unrecved_bytes += p->tot_len;
-  } else
-#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
-  {
-    /* Inform TCP that we have taken the data. */
-    tcp_recved(pcb, p->tot_len);
-  }
-
-#if LWIP_HTTPD_SUPPORT_POST
-  if (hs->post_content_len_left > 0) {
-    /* reset idle counter when POST data is received */
-    hs->retries = 0;
-    /* this is data for a POST, pass the complete pbuf to the application */
-    http_post_rxpbuf(hs, p);
-    /* pbuf is passed to the application, don't free it! */
-    if (hs->post_content_len_left == 0) {
-      /* all data received, send response or close connection */
-      http_send(pcb, hs);
-    }
-    return ERR_OK;
-  } else
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-  {
-    if (hs->handle == NULL) {
-      err_t parsed = http_parse_request(p, hs, pcb);
-      LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK
-        || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE);
-#if LWIP_HTTPD_SUPPORT_REQUESTLIST
-      if (parsed != ERR_INPROGRESS) {
-        /* request fully parsed or error */
-        if (hs->req != NULL) {
-          pbuf_free(hs->req);
-          hs->req = NULL;
-        }
-      }
-#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
-      pbuf_free(p);
-      if (parsed == ERR_OK) {
-#if LWIP_HTTPD_SUPPORT_POST
-       if (hs->post_content_len_left == 0)
-#endif /* LWIP_HTTPD_SUPPORT_POST */
-        {
-          LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void*)hs->file, hs->left));
-          http_send(pcb, hs);
-        }
-      } else if (parsed == ERR_ARG) {
-        /* @todo: close on ERR_USE? */
-        http_close_conn(pcb, hs);
-      }
-    } else {
-      LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n"));
-      /* already sending but still receiving data, we might want to RST here? */
-      pbuf_free(p);
-    }
-  }
-  return ERR_OK;
-}
-
-/**
- * A new incoming connection has been accepted.
- */
-static err_t
-http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
-{
-  struct http_state *hs;
-  LWIP_UNUSED_ARG(err);
-  LWIP_UNUSED_ARG(arg);
-  LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg));
-
-  if ((err != ERR_OK) || (pcb == NULL)) {
-    return ERR_VAL;
-  }
-
-  /* Set priority */
-  tcp_setprio(pcb, HTTPD_TCP_PRIO);
-
-  /* Allocate memory for the structure that holds the state of the
-     connection - initialized by that function. */
-  hs = http_state_alloc();
-  if (hs == NULL) {
-    LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n"));
-    return ERR_MEM;
-  }
-  hs->pcb = pcb;
-
-  /* Tell TCP that this is the structure we wish to be passed for our
-     callbacks. */
-  tcp_arg(pcb, hs);
-
-  /* Set up the various callback functions */
-  tcp_recv(pcb, http_recv);
-  tcp_err(pcb, http_err);
-  tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL);
-  tcp_sent(pcb, http_sent);
-
-  return ERR_OK;
-}
-
-/**
- * @ingroup httpd
- * Initialize the httpd: set up a listening PCB and bind it to the defined port
- */
-void
-httpd_init(void)
-{
-  struct tcp_pcb *pcb;
-  err_t err;
-
-#if HTTPD_USE_MEM_POOL
-  LWIP_MEMPOOL_INIT(HTTPD_STATE);
-#if LWIP_HTTPD_SSI
-  LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE);
-#endif
-#endif
-  LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n"));
-
-  pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
-  LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL);
-  tcp_setprio(pcb, HTTPD_TCP_PRIO);
-  /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
-  err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
-  LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
-  pcb = tcp_listen(pcb);
-  LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
-  tcp_accept(pcb, http_accept);
-}
-
-#if LWIP_HTTPD_SSI
-/**
- * Set the SSI handler function.
- *
- * @param ssi_handler the SSI handler function
- * @param tags an array of SSI tag strings to search for in SSI-enabled files
- * @param num_tags number of tags in the 'tags' array
- */
-void
-http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags)
-{
-  LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n"));
-
-  LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL);
-  g_pfnSSIHandler = ssi_handler;
-
-#if LWIP_HTTPD_SSI_RAW
-  LWIP_UNUSED_ARG(tags);
-  LWIP_UNUSED_ARG(num_tags);
-#else /* LWIP_HTTPD_SSI_RAW */
-  LWIP_ASSERT("no tags given", tags != NULL);
-  LWIP_ASSERT("invalid number of tags", num_tags > 0);
-
-  g_ppcTags = tags;
-  g_iNumTags = num_tags;
-#endif /* !LWIP_HTTPD_SSI_RAW */
-}
-#endif /* LWIP_HTTPD_SSI */
-
-#if LWIP_HTTPD_CGI
-/**
- * Set an array of CGI filenames/handler functions
- *
- * @param cgis an array of CGI filenames/handler functions
- * @param num_handlers number of elements in the 'cgis' array
- */
-void
-http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
-{
-  LWIP_ASSERT("no cgis given", cgis != NULL);
-  LWIP_ASSERT("invalid number of handlers", num_handlers > 0);
-
-  g_pCGIs = cgis;
-  g_iNumCGIs = num_handlers;
-}
-#endif /* LWIP_HTTPD_CGI */
-
-#endif /* LWIP_TCP */

+ 0 - 114
components/net/lwip-2.0.0/src/apps/httpd/httpd_structs.h

@@ -1,114 +0,0 @@
-#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 */

+ 0 - 97
components/net/lwip-2.0.0/src/apps/httpd/makefsdata/makefsdata

@@ -1,97 +0,0 @@
-#!/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");

+ 0 - 1033
components/net/lwip-2.0.0/src/apps/httpd/makefsdata/makefsdata.c

@@ -1,1033 +0,0 @@
-/**
- * makefsdata: Converts a directory structure for use with the lwIP httpd.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Jim Pettinato
- *         Simon Goldschmidt
- *
- * @todo:
- * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and
- *   PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include "windows.h"
-#else
-#include <dir.h>
-#endif
-#include <dos.h>
-#include <string.h>
-#include <time.h>
-#include <sys/stat.h>
-
-/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks).
- * Since nearly all browsers support this, this is a good way to reduce ROM size.
- * To compress the files, "miniz.c" must be downloaded seperately.
- */
-#ifndef MAKEFS_SUPPORT_DEFLATE
-#define MAKEFS_SUPPORT_DEFLATE 0
-#endif
-
-#define COPY_BUFSIZE (1024*1024) /* 1 MByte */
-
-#if MAKEFS_SUPPORT_DEFLATE
-#include "../miniz.c"
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint;
-
-#define my_max(a,b) (((a) > (b)) ? (a) : (b))
-#define my_min(a,b) (((a) < (b)) ? (a) : (b))
-
-/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression.
-   COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */
-#define COMP_OUT_BUF_SIZE COPY_BUFSIZE
-
-/* OUT_BUF_SIZE is the size of the output buffer used during decompression.
-   OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */
-#define OUT_BUF_SIZE COPY_BUFSIZE
-static uint8 s_outbuf[OUT_BUF_SIZE];
-static uint8 s_checkbuf[OUT_BUF_SIZE];
-
-/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k).
-   This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */
-tdefl_compressor g_deflator;
-tinfl_decompressor g_inflator;
-
-int deflate_level = 10; /* default compression level, can be changed via command line */
-#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]"
-#else /* MAKEFS_SUPPORT_DEFLATE */
-#define USAGE_ARG_DEFLATE ""
-#endif /* MAKEFS_SUPPORT_DEFLATE */
-
-/* Compatibility defines Win32 vs. DOS */
-#ifdef WIN32
-
-#define FIND_T                        WIN32_FIND_DATAA
-#define FIND_T_FILENAME(fInfo)        (fInfo.cFileName)
-#define FIND_T_IS_DIR(fInfo)          ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
-#define FIND_T_IS_FILE(fInfo)         ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
-#define FIND_RET_T                    HANDLE
-#define FINDFIRST_FILE(path, result)  FindFirstFileA(path, result)
-#define FINDFIRST_DIR(path, result)   FindFirstFileA(path, result)
-#define FINDNEXT(ff_res, result)      FindNextFileA(ff_res, result)
-#define FINDFIRST_SUCCEEDED(ret)      (ret != INVALID_HANDLE_VALUE)
-#define FINDNEXT_SUCCEEDED(ret)       (ret == TRUE)
-
-#define GETCWD(path, len)             GetCurrentDirectoryA(len, path)
-#define CHDIR(path)                   SetCurrentDirectoryA(path)
-#define CHDIR_SUCCEEDED(ret)          (ret == TRUE)
-
-#else
-
-#define FIND_T                        struct ffblk
-#define FIND_T_FILENAME(fInfo)        (fInfo.ff_name)
-#define FIND_T_IS_DIR(fInfo)          ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC)
-#define FIND_T_IS_FILE(fInfo)         (1)
-#define FIND_RET_T                    int
-#define FINDFIRST_FILE(path, result)  findfirst(path, result, FA_ARCH)
-#define FINDFIRST_DIR(path, result)   findfirst(path, result, FA_DIREC)
-#define FINDNEXT(ff_res, result)      FindNextFileA(ff_res, result)
-#define FINDFIRST_SUCCEEDED(ret)      (ret == 0)
-#define FINDNEXT_SUCCEEDED(ret)       (ret == 0)
-
-#define GETCWD(path, len)             getcwd(path, len)
-#define CHDIR(path)                   chdir(path)
-#define CHDIR_SUCCEEDED(ret)          (ret == 0)
-
-#endif
-
-#define NEWLINE     "\r\n"
-#define NEWLINE_LEN 2
-
-/* define this to get the header variables we use to build HTTP headers */
-#define LWIP_HTTPD_DYNAMIC_HEADERS 1
-#define LWIP_HTTPD_SSI             1
-#include "lwip/init.h"
-#include "../httpd_structs.h"
-#include "lwip/apps/fs.h"
-
-#include "../core/inet_chksum.c"
-#include "../core/def.c"
-
-/** (Your server name here) */
-const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n";
-char serverIDBuffer[1024];
-
-/* change this to suit your MEM_ALIGNMENT */
-#define PAYLOAD_ALIGNMENT 4
-/* set this to 0 to prevent aligning payload */
-#define ALIGN_PAYLOAD 1
-/* define this to a type that has the required alignment */
-#define PAYLOAD_ALIGN_TYPE "unsigned int"
-static int payload_alingment_dummy_counter = 0;
-
-#define HEX_BYTES_PER_LINE 16
-
-#define MAX_PATH_LEN 256
-
-struct file_entry
-{
-   struct file_entry* next;
-   const char* filename_c;
-};
-
-int process_sub(FILE *data_file, FILE *struct_file);
-int process_file(FILE *data_file, FILE *struct_file, const char *filename);
-int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len,
-                           u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed);
-int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i);
-int s_put_ascii(char *buf, const char *ascii_string, int len, int *i);
-void concat_files(const char *file1, const char *file2, const char *targetfile);
-int check_path(char* path, size_t size);
-
-/* 5 bytes per char + 3 bytes per line */
-static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)];
-
-char curSubdir[MAX_PATH_LEN];
-char lastFileVar[MAX_PATH_LEN];
-char hdr_buf[4096];
-
-unsigned char processSubs = 1;
-unsigned char includeHttpHeader = 1;
-unsigned char useHttp11 = 0;
-unsigned char supportSsi = 1;
-unsigned char precalcChksum = 0;
-unsigned char includeLastModified = 0;
-#if MAKEFS_SUPPORT_DEFLATE
-unsigned char deflateNonSsiFiles = 0;
-size_t deflatedBytesReduced = 0;
-size_t overallDataBytes = 0;
-#endif
-
-struct file_entry* first_file = NULL;
-struct file_entry* last_file = NULL;
-
-static void print_usage(void)
-{
-  printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:<filename>] [-m] [-svr:<name>]" USAGE_ARG_DEFLATE NEWLINE NEWLINE);
-  printf("   targetdir: relative or absolute path to files to convert" NEWLINE);
-  printf("   switch -s: toggle processing of subdirectories (default is on)" NEWLINE);
-  printf("   switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE);
-  printf("   switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE);
-  printf("   switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE);
-  printf("   switch -c: precalculate checksums for all pages (default is off)" NEWLINE);
-  printf("   switch -f: target filename (default is \"fsdata.c\")" NEWLINE);
-  printf("   switch -m: include \"Last-Modified\" header based on file time" NEWLINE);
-  printf("   switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE);
-#if MAKEFS_SUPPORT_DEFLATE
-  printf("   switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE);
-  printf("                 ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE);
-#endif
-  printf("   if targetdir not specified, htmlgen will attempt to" NEWLINE);
-  printf("   process files in subdirectory 'fs'" NEWLINE);
-}
-
-int main(int argc, char *argv[])
-{
-  char path[MAX_PATH_LEN];
-  char appPath[MAX_PATH_LEN];
-  FILE *data_file;
-  FILE *struct_file;
-  int filesProcessed;
-  int i;
-  char targetfile[MAX_PATH_LEN];
-  strcpy(targetfile, "fsdata.c");
-
-  memset(path, 0, sizeof(path));
-  memset(appPath, 0, sizeof(appPath));
-
-  printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE);
-  printf("     by Jim Pettinato               - circa 2003 " NEWLINE);
-  printf("     extended by Simon Goldschmidt  - 2009 " NEWLINE NEWLINE);
-
-  strcpy(path, "fs");
-  for (i = 1; i < argc; i++) {
-    if (argv[i] == NULL) {
-      continue;
-    }
-    if (argv[i][0] == '-') {
-      if (strstr(argv[i], "-svr:") == argv[i]) {
-        snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]);
-        serverID = serverIDBuffer;
-        printf("Using Server-ID: \"%s\"\n", serverID);
-      } else if (strstr(argv[i], "-s") == argv[i]) {
-        processSubs = 0;
-      } else if (strstr(argv[i], "-e") == argv[i]) {
-        includeHttpHeader = 0;
-      } else if (strstr(argv[i], "-11") == argv[i]) {
-        useHttp11 = 1;
-      } else if (strstr(argv[i], "-nossi") == argv[i]) {
-        supportSsi = 0;
-      } else if (strstr(argv[i], "-c") == argv[i]) {
-        precalcChksum = 1;
-      } else if (strstr(argv[i], "-f:") == argv[i]) {
-        strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1);
-        targetfile[sizeof(targetfile) - 1] = 0;
-        printf("Writing to file \"%s\"\n", targetfile);
-      } else if (strstr(argv[i], "-m") == argv[i]) {
-        includeLastModified = 1;
-      } else if (strstr(argv[i], "-defl") == argv[i]) {
-#if MAKEFS_SUPPORT_DEFLATE
-        char* colon = strstr(argv[i], ":");
-        if (colon) {
-          if (colon[1] != 0) {
-            int defl_level = atoi(&colon[1]);
-            if ((defl_level >= 0) && (defl_level <= 10)) {
-              deflate_level = defl_level;
-            } else {
-              printf("ERROR: deflate level must be [0..10]" NEWLINE);
-              exit(0);
-            }
-          }
-        }
-        deflateNonSsiFiles = 1;
-        printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level);
-#else
-        printf("WARNING: Deflate support is disabled\n");
-#endif
-      } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) {
-        print_usage();
-        exit(0);
-      }
-    } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) {
-      print_usage();
-      exit(0);
-    } else {
-      strncpy(path, argv[i], sizeof(path)-1);
-      path[sizeof(path)-1] = 0;
-    }
-  }
-
-  if (!check_path(path, sizeof(path))) {
-    printf("Invalid path: \"%s\"." NEWLINE, path);
-    exit(-1);
-  }
-
-  GETCWD(appPath, MAX_PATH_LEN);
-  /* if command line param or subdir named 'fs' not found spout usage verbiage */
-  if (!CHDIR_SUCCEEDED(CHDIR(path))) {
-    /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */
-    printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path);
-    print_usage();
-    exit(-1);
-  }
-  CHDIR(appPath);
-
-  printf("HTTP %sheader will %s statically included." NEWLINE,
-    (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""),
-    (includeHttpHeader ? "be" : "not be"));
-
-  sprintf(curSubdir, "");  /* start off in web page's root directory - relative paths */
-  printf("  Processing all files in directory %s", path);
-  if (processSubs) {
-    printf(" and subdirectories..." NEWLINE NEWLINE);
-  } else {
-    printf("..." NEWLINE NEWLINE);
-  }
-
-  data_file = fopen("fsdata.tmp", "wb");
-  if (data_file == NULL) {
-    printf("Failed to create file \"fsdata.tmp\"\n");
-    exit(-1);
-  }
-  struct_file = fopen("fshdr.tmp", "wb");
-  if (struct_file == NULL) {
-    printf("Failed to create file \"fshdr.tmp\"\n");
-    fclose(data_file);
-    exit(-1);
-  }
-
-  CHDIR(path);
-
-  fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE);
-  fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE);
-  fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE);
-
-  fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE);
-  /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */
-  fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE);
-  /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */
-  fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE);
-
-  /* define alignment defines */
-#if ALIGN_PAYLOAD
-  fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE);
-#endif
-  fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE"  NEWLINE "#define FSDATA_ALIGN_PRE"  NEWLINE "#endif" NEWLINE);
-  fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE);
-#if ALIGN_PAYLOAD
-  fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE);
-#endif
-
-  sprintf(lastFileVar, "NULL");
-
-  filesProcessed = process_sub(data_file, struct_file);
-
-  /* data_file now contains all of the raw data.. now append linked list of
-   * file header structs to allow embedded app to search for a file name */
-  fprintf(data_file, NEWLINE NEWLINE);
-  fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar);
-  fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed);
-
-  fclose(data_file);
-  fclose(struct_file);
-
-  CHDIR(appPath);
-  /* append struct_file to data_file */
-  printf(NEWLINE "Creating target file..." NEWLINE NEWLINE);
-  concat_files("fsdata.tmp", "fshdr.tmp", targetfile);
-
-  /* if succeeded, delete the temporary files */
-  if (remove("fsdata.tmp") != 0) {
-    printf("Warning: failed to delete fsdata.tmp\n");
-  }
-  if (remove("fshdr.tmp") != 0) {
-    printf("Warning: failed to delete fshdr.tmp\n");
-  }
-
-  printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed);
-#if MAKEFS_SUPPORT_DEFLATE
-  if (deflateNonSsiFiles) {
-    printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE,
-      (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes));
-  }
-#endif
-  printf(NEWLINE);
-
-  while (first_file != NULL) {
-     struct file_entry* fe = first_file;
-     first_file = fe->next;
-     free(fe);
-  }
-
-  return 0;
-}
-
-int check_path(char* path, size_t size)
-{
-  size_t slen;
-  if (path[0] == 0) {
-    /* empty */
-    return 0;
-  }
-  slen = strlen(path);
-  if (slen >= size) {
-    /* not NULL-terminated */
-    return 0;
-  }
-  while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) {
-    /* path should not end with trailing backslash */
-    path[slen] = 0;
-    slen--;
-  }
-  if (slen == 0) {
-    return 0;
-  }
-  return 1;
-}
-
-static void copy_file(const char *filename_in, FILE *fout)
-{
-  FILE *fin;
-  size_t len;
-  void* buf;
-  fin = fopen(filename_in, "rb");
-  if (fin == NULL) {
-    printf("Failed to open file \"%s\"\n", filename_in);
-    exit(-1);
-  }
-  buf = malloc(COPY_BUFSIZE);
-  while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) {
-    fwrite(buf, 1, len, fout);
-  }
-  free(buf);
-  fclose(fin);
-}
-
-void concat_files(const char *file1, const char *file2, const char *targetfile)
-{
-  FILE *fout;
-  fout = fopen(targetfile, "wb");
-  if (fout == NULL) {
-    printf("Failed to open file \"%s\"\n", targetfile);
-    exit(-1);
-  }
-  copy_file(file1, fout);
-  copy_file(file2, fout);
-  fclose(fout);
-}
-
-int process_sub(FILE *data_file, FILE *struct_file)
-{
-  FIND_T fInfo;
-  FIND_RET_T fret;
-  int filesProcessed = 0;
-
-  if (processSubs) {
-    /* process subs recursively */
-    size_t sublen = strlen(curSubdir);
-    size_t freelen = sizeof(curSubdir) - sublen - 1;
-    LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir));
-    fret = FINDFIRST_DIR("*", &fInfo);
-    if (FINDFIRST_SUCCEEDED(fret)) {
-      do {
-        const char *curName = FIND_T_FILENAME(fInfo);
-        if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) {
-          continue;
-        }
-        if (!FIND_T_IS_DIR(fInfo)) {
-          continue;
-        }
-        if (freelen > 0) {
-           CHDIR(curName);
-           strncat(curSubdir, "/", freelen);
-           strncat(curSubdir, curName, freelen - 1);
-           curSubdir[sizeof(curSubdir) - 1] = 0;
-           printf("processing subdirectory %s/..." NEWLINE, curSubdir);
-           filesProcessed += process_sub(data_file, struct_file);
-           CHDIR("..");
-           curSubdir[sublen] = 0;
-        } else {
-           printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName);
-        }
-      } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo)));
-    }
-  }
-
-  fret = FINDFIRST_FILE("*.*", &fInfo);
-  if (FINDFIRST_SUCCEEDED(fret)) {
-    /* at least one file in directory */
-    do {
-      if (FIND_T_IS_FILE(fInfo)) {
-        const char *curName = FIND_T_FILENAME(fInfo);
-        printf("processing %s/%s..." NEWLINE, curSubdir, curName);
-        if (process_file(data_file, struct_file, curName) < 0) {
-          printf(NEWLINE "Error... aborting" NEWLINE);
-          return -1;
-        }
-        filesProcessed++;
-      }
-    } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo)));
-  }
-  return filesProcessed;
-}
-
-u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed)
-{
-  FILE *inFile;
-  size_t fsize = 0;
-  u8_t* buf;
-  size_t r;
-  int rs;
-  inFile = fopen(filename, "rb");
-  if (inFile == NULL) {
-    printf("Failed to open file \"%s\"\n", filename);
-    exit(-1);
-  }
-  fseek(inFile, 0, SEEK_END);
-  rs = ftell(inFile);
-  if (rs < 0) {
-     printf("ftell failed with %d\n", errno);
-     exit(-1);
-  }
-  fsize = (size_t)rs;
-  fseek(inFile, 0, SEEK_SET);
-  buf = (u8_t*)malloc(fsize);
-  LWIP_ASSERT("buf != NULL", buf != NULL);
-  r = fread(buf, 1, fsize, inFile);
-  *file_size = fsize;
-  *is_compressed = 0;
-#if MAKEFS_SUPPORT_DEFLATE
-  overallDataBytes += fsize;
-  if (deflateNonSsiFiles) {
-    if (can_be_compressed) {
-      if (fsize < OUT_BUF_SIZE) {
-        u8_t* ret_buf;
-        tdefl_status status;
-        size_t in_bytes = fsize;
-        size_t out_bytes = OUT_BUF_SIZE;
-        const void *next_in = buf;
-        void *next_out = s_outbuf;
-        /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */
-        mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
-        if (!deflate_level) {
-          comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
-        }
-        status = tdefl_init(&g_deflator, NULL, NULL, comp_flags);
-        if (status != TDEFL_STATUS_OKAY) {
-          printf("tdefl_init() failed!\n");
-          exit(-1);
-        }
-        memset(s_outbuf, 0, sizeof(s_outbuf));
-        status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH);
-        if (status != TDEFL_STATUS_DONE) {
-          printf("deflate failed: %d\n", status);
-          exit(-1);
-        }
-        LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE);
-        if (out_bytes < fsize) {
-          ret_buf = (u8_t*)malloc(out_bytes);
-          LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL);
-          memcpy(ret_buf, s_outbuf, out_bytes);
-          {
-            /* sanity-check compression be inflating and comparing to the original */
-            tinfl_status dec_status;
-            tinfl_decompressor inflator;
-            size_t dec_in_bytes = out_bytes;
-            size_t dec_out_bytes = OUT_BUF_SIZE;
-            next_out = s_checkbuf;
-
-            tinfl_init(&inflator);
-            memset(s_checkbuf, 0, sizeof(s_checkbuf));
-            dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0);
-            LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE);
-            LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes);
-            LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize));
-          }
-          /* free original buffer, use compressed data + size */
-          free(buf);
-          buf = ret_buf;
-          *file_size = out_bytes;
-          printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize));
-          deflatedBytesReduced += (size_t)(fsize - out_bytes);
-          *is_compressed = 1;
-        } else {
-          printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize));
-        }
-      } else {
-        printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE);
-      }
-    } else {
-      printf(" - SSI file, cannot be compressed" NEWLINE);
-    }
-  }
-#else
-  LWIP_UNUSED_ARG(can_be_compressed);
-#endif
-  fclose(inFile);
-  return buf;
-}
-
-void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size)
-{
-  size_t written, i, src_off=0;
-
-  size_t off = 0;
-  for (i = 0; i < file_size; i++) {
-    LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5);
-    sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]);
-    off += 5;
-    if ((++src_off % HEX_BYTES_PER_LINE) == 0) {
-      LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN);
-      memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN);
-      off += NEWLINE_LEN;
-    }
-    if (off + 20 >= sizeof(file_buffer_c)) {
-      written = fwrite(file_buffer_c, 1, off, data_file);
-      LWIP_ASSERT("written == off", written == off);
-      off = 0;
-    }
-  }
-  written = fwrite(file_buffer_c, 1, off, data_file);
-  LWIP_ASSERT("written == off", written == off);
-}
-
-int write_checksums(FILE *struct_file, const char *varname,
-                    u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size)
-{
-  int chunk_size = TCP_MSS;
-  int offset, src_offset;
-  size_t len;
-  int i = 0;
-#if LWIP_TCP_TIMESTAMPS
-  /* when timestamps are used, usable space is 12 bytes less per segment */
-  chunk_size -= 12;
-#endif
-
-  fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE);
-  fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname);
-
-  if (hdr_len > 0) {
-    /* add checksum for HTTP header */
-    fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len);
-    i++;
-  }
-  src_offset = 0;
-  for (offset = hdr_len; ; offset += len) {
-    unsigned short chksum;
-    void* data = (void*)&file_data[src_offset];
-    len = LWIP_MIN(chunk_size, (int)file_size - src_offset);
-    if (len == 0) {
-      break;
-    }
-    chksum = ~inet_chksum(data, (u16_t)len);
-    /* add checksum for data */
-    fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len);
-    i++;
-  }
-  fprintf(struct_file, "};" NEWLINE);
-  fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE);
-  return i;
-}
-
-static int is_valid_char_for_c_var(char x)
-{
-   if (((x >= 'A') && (x <= 'Z')) ||
-       ((x >= 'a') && (x <= 'z')) ||
-       ((x >= '0') && (x <= '9')) ||
-        (x == '_')) {
-      return 1;
-   }
-   return 0;
-}
-
-static void fix_filename_for_c(char* qualifiedName, size_t max_len)
-{
-   struct file_entry* f;
-   size_t len = strlen(qualifiedName);
-   char *new_name = (char*)malloc(len + 2);
-   int filename_ok;
-   int cnt = 0;
-   size_t i;
-   if (len + 3 == max_len) {
-      printf("File name too long: \"%s\"\n", qualifiedName);
-      exit(-1);
-   }
-   strcpy(new_name, qualifiedName);
-   for (i = 0; i < len; i++) {
-      if (!is_valid_char_for_c_var(new_name[i])) {
-         new_name[i] = '_';
-      }
-   }
-   do {
-      filename_ok = 1;
-      for (f = first_file; f != NULL; f = f->next) {
-         if (!strcmp(f->filename_c, new_name)) {
-            filename_ok = 0;
-            cnt++;
-            /* try next unique file name */
-            sprintf(&new_name[len], "%d", cnt);
-            break;
-         }
-      }
-   } while (!filename_ok && (cnt < 999));
-   if (!filename_ok) {
-      printf("Failed to get unique file name: \"%s\"\n", qualifiedName);
-      exit(-1);
-   }
-   strcpy(qualifiedName, new_name);
-   free(new_name);
-}
-
-static void register_filename(const char* qualifiedName)
-{
-   struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry));
-   fe->filename_c = strdup(qualifiedName);
-   fe->next = NULL;
-   if (first_file == NULL) {
-      first_file = last_file = fe;
-   } else {
-      last_file->next = fe;
-      last_file = fe;
-   }
-}
-
-int is_ssi_file(const char* filename)
-{
-  size_t loop;
-  for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
-    if (strstr(filename, g_pcSSIExtensions[loop])) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-int process_file(FILE *data_file, FILE *struct_file, const char *filename)
-{
-  char varname[MAX_PATH_LEN];
-  int i = 0;
-  char qualifiedName[MAX_PATH_LEN];
-  int file_size;
-  u16_t http_hdr_chksum = 0;
-  u16_t http_hdr_len = 0;
-  int chksum_count = 0;
-  u8_t flags = 0;
-  const char* flags_str;
-  u8_t has_content_len;
-  u8_t* file_data;
-  int is_compressed = 0;
-
-  /* create qualified name (@todo: prepend slash or not?) */
-  sprintf(qualifiedName,"%s/%s", curSubdir, filename);
-  /* create C variable name */
-  strcpy(varname, qualifiedName);
-  /* convert slashes & dots to underscores */
-  fix_filename_for_c(varname, MAX_PATH_LEN);
-  register_filename(varname);
-#if ALIGN_PAYLOAD
-  /* to force even alignment of array, type 1 */
-  fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE);
-  fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++);
-  fprintf(data_file, "#endif" NEWLINE);
-#endif /* ALIGN_PAYLOAD */
-  fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname);
-  /* encode source file name (used by file system, not returned to browser) */
-  fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1);
-  file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i);
-#if ALIGN_PAYLOAD
-  /* pad to even number of bytes to assure payload is on aligned boundary */
-  while(i % PAYLOAD_ALIGNMENT != 0) {
-    fprintf(data_file, "0x%02.2x,", 0);
-    i++;
-  }
-#endif /* ALIGN_PAYLOAD */
-  fprintf(data_file, NEWLINE);
-
-  has_content_len = !is_ssi_file(filename);
-  file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed);
-  if (includeHttpHeader) {
-    file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed);
-    flags = FS_FILE_FLAGS_HEADER_INCLUDED;
-    if (has_content_len) {
-      flags |= FS_FILE_FLAGS_HEADER_PERSISTENT;
-    }
-  }
-  if (precalcChksum) {
-    chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size);
-  }
-
-  /* build declaration of struct fsdata_file in temp file */
-  fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname);
-  fprintf(struct_file, "file_%s," NEWLINE, lastFileVar);
-  fprintf(struct_file, "data_%s," NEWLINE, varname);
-  fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i);
-  fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i);
-  switch(flags)
-  {
-  case(FS_FILE_FLAGS_HEADER_INCLUDED):
-     flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED";
-     break;
-  case(FS_FILE_FLAGS_HEADER_PERSISTENT):
-     flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT";
-     break;
-  case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT):
-     flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT";
-     break;
-  default:
-     flags_str = "0";
-     break;
-  }
-  fprintf(struct_file, "%s," NEWLINE, flags_str);
-  if (precalcChksum) {
-    fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE);
-    fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname);
-    fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE);
-  }
-  fprintf(struct_file, "}};" NEWLINE NEWLINE);
-  strcpy(lastFileVar, varname);
-
-  /* write actual file contents */
-  i = 0;
-  fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size);
-  process_file_data(data_file, file_data, file_size);
-  fprintf(data_file, "};" NEWLINE NEWLINE);
-  free(file_data);
-  return 0;
-}
-
-int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len,
-                           u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed)
-{
-  int i = 0;
-  int response_type = HTTP_HDR_OK;
-  const char* file_type;
-  const char *cur_string;
-  size_t cur_len;
-  int written = 0;
-  size_t hdr_len = 0;
-  u16_t acc;
-  const char *file_ext;
-  int j;
-  u8_t provide_last_modified = includeLastModified;
-
-  memset(hdr_buf, 0, sizeof(hdr_buf));
-
-  if (useHttp11) {
-    response_type = HTTP_HDR_OK_11;
-  }
-
-  fprintf(data_file, NEWLINE "/* HTTP header */");
-  if (strstr(filename, "404") == filename) {
-    response_type = HTTP_HDR_NOT_FOUND;
-    if (useHttp11) {
-      response_type = HTTP_HDR_NOT_FOUND_11;
-    }
-  } else if (strstr(filename, "400") == filename) {
-    response_type = HTTP_HDR_BAD_REQUEST;
-    if (useHttp11) {
-      response_type = HTTP_HDR_BAD_REQUEST_11;
-    }
-  } else if (strstr(filename, "501") == filename) {
-    response_type = HTTP_HDR_NOT_IMPL;
-    if (useHttp11) {
-      response_type = HTTP_HDR_NOT_IMPL_11;
-    }
-  }
-  cur_string = g_psHTTPHeaderStrings[response_type];
-  cur_len = strlen(cur_string);
-  fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
-  written += file_put_ascii(data_file, cur_string, cur_len, &i);
-  i = 0;
-  if (precalcChksum) {
-    memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-    hdr_len += cur_len;
-  }
-
-  cur_string = serverID;
-  cur_len = strlen(cur_string);
-  fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
-  written += file_put_ascii(data_file, cur_string, cur_len, &i);
-  i = 0;
-  if (precalcChksum) {
-    memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-    hdr_len += cur_len;
-  }
-
-  file_ext = filename;
-  if (file_ext != NULL) {
-    while(strstr(file_ext, ".") != NULL) {
-      file_ext = strstr(file_ext, ".");
-      file_ext++;
-    }
-  }
-  if ((file_ext == NULL) || (*file_ext == 0)) {
-    printf("failed to get extension for file \"%s\", using default.\n", filename);
-    file_type = HTTP_HDR_DEFAULT_TYPE;
-  } else {
-    file_type = NULL;
-    for (j = 0; j < NUM_HTTP_HEADERS; j++) {
-      if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) {
-        file_type = g_psHTTPHeaders[j].content_type;
-        break;
-      }
-    }
-    if (file_type == NULL) {
-      printf("failed to get file type for extension \"%s\", using default.\n", file_ext);
-      file_type = HTTP_HDR_DEFAULT_TYPE;
-    }
-  }
-
-  /* Content-Length is used for persistent connections in HTTP/1.1 but also for
-     download progress in older versions
-     @todo: just use a big-enough buffer and let the HTTPD send spaces? */
-  if (provide_content_len) {
-    char intbuf[MAX_PATH_LEN];
-    int content_len = file_size;
-    memset(intbuf, 0, sizeof(intbuf));
-    cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
-    cur_len = strlen(cur_string);
-    fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2);
-    written += file_put_ascii(data_file, cur_string, cur_len, &i);
-    if (precalcChksum) {
-      memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-      hdr_len += cur_len;
-    }
-
-    _itoa(content_len, intbuf, 10);
-    strcat(intbuf, "\r\n");
-    cur_len = strlen(intbuf);
-    written += file_put_ascii(data_file, intbuf, cur_len, &i);
-    i = 0;
-    if (precalcChksum) {
-      memcpy(&hdr_buf[hdr_len], intbuf, cur_len);
-      hdr_len += cur_len;
-    }
-  }
-  if (provide_last_modified) {
-    char modbuf[256];
-    struct stat stat_data;
-    struct tm* t;
-    memset(modbuf, 0, sizeof(modbuf));
-    memset(&stat_data, 0, sizeof(stat_data));
-    cur_string = modbuf;
-    strcpy(modbuf, "Last-Modified: ");
-    if (stat(filename, &stat_data) != 0) {
-       printf("stat(%s) failed with error %d\n", filename, errno);
-       exit(-1);
-    }
-    t = gmtime(&stat_data.st_mtime);
-    if (t == NULL) {
-       printf("gmtime() failed with error %d\n", errno);
-       exit(-1);
-    }
-    strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t);
-    cur_len = strlen(cur_string);
-    fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2);
-    written += file_put_ascii(data_file, cur_string, cur_len, &i);
-    if (precalcChksum) {
-      memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-      hdr_len += cur_len;
-    }
-
-    modbuf[0] = 0;
-    strcat(modbuf, "\r\n");
-    cur_len = strlen(modbuf);
-    written += file_put_ascii(data_file, modbuf, cur_len, &i);
-    i = 0;
-    if (precalcChksum) {
-      memcpy(&hdr_buf[hdr_len], modbuf, cur_len);
-      hdr_len += cur_len;
-    }
-  }
-
-  /* HTTP/1.1 implements persistent connections */
-  if (useHttp11) {
-    if (provide_content_len) {
-      cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE];
-    } else {
-      /* no Content-Length available, so a persistent connection is no possible
-         because the client does not know the data length */
-      cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
-    }
-    cur_len = strlen(cur_string);
-    fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
-    written += file_put_ascii(data_file, cur_string, cur_len, &i);
-    i = 0;
-    if (precalcChksum) {
-      memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-      hdr_len += cur_len;
-    }
-  }
-
-#if MAKEFS_SUPPORT_DEFLATE
-  if (is_compressed) {
-    /* tell the client about the deflate encoding */
-    LWIP_ASSERT("error", deflateNonSsiFiles);
-    cur_string = "Content-Encoding: deflate\r\n";
-    cur_len = strlen(cur_string);
-    fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
-    written += file_put_ascii(data_file, cur_string, cur_len, &i);
-    i = 0;
-  }
-#else
-  LWIP_UNUSED_ARG(is_compressed);
-#endif
-
-  /* write content-type, ATTENTION: this includes the double-CRLF! */
-  cur_string = file_type;
-  cur_len = strlen(cur_string);
-  fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
-  written += file_put_ascii(data_file, cur_string, cur_len, &i);
-  i = 0;
-
-  /* ATTENTION: headers are done now (double-CRLF has been written!) */
-
-  if (precalcChksum) {
-    memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
-    hdr_len += cur_len;
-
-    LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff);
-    LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len);
-    acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len);
-    *http_hdr_len = (u16_t)hdr_len;
-    *http_hdr_chksum = acc;
-  }
-
-  return written;
-}
-
-int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i)
-{
-  int x;
-  for (x = 0; x < len; x++) {
-    unsigned char cur = ascii_string[x];
-    fprintf(file, "0x%02.2x,", cur);
-    if ((++(*i) % HEX_BYTES_PER_LINE) == 0) {
-      fprintf(file, NEWLINE);
-    }
-  }
-  return len;
-}
-
-int s_put_ascii(char *buf, const char *ascii_string, int len, int *i)
-{
-  int x;
-  int idx = 0;
-  for (x = 0; x < len; x++) {
-    unsigned char cur = ascii_string[x];
-    sprintf(&buf[idx], "0x%02.2x,", cur);
-    idx += 5;
-    if ((++(*i) % HEX_BYTES_PER_LINE) == 0) {
-      sprintf(&buf[idx], NEWLINE);
-      idx += NEWLINE_LEN;
-    }
-  }
-  return len;
-}

+ 0 - 13
components/net/lwip-2.0.0/src/apps/httpd/makefsdata/readme.txt

@@ -1,13 +0,0 @@
-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'.

+ 0 - 663
components/net/lwip-2.0.0/src/apps/lwiperf/lwiperf.c

@@ -1,663 +0,0 @@
-/**
- * @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
-
-/** 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 = (void*)(size_t)&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;
-      }
-    }
-    packet_idx += i;
-#else
-    packet_idx += q->len;
-#endif
-  }
-  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(IP4_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 */

+ 0 - 2031
components/net/lwip-2.0.0/src/apps/mdns/mdns.c

@@ -1,2031 +0,0 @@
-/**
- * @file
- * MDNS responder implementation
- *
- * @defgroup mdns MDNS
- * @ingroup apps
- *
- * RFC 6762 - Multicast DNS\n
- * RFC 6763 - DNS-Based Service Discovery\n
- * 
- * @verbinclude mdns.txt
- * 
- * Things left to implement:
- * -------------------------
- *
- * - Probing/conflict resolution
- * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off...
- * - Checking that source address of unicast requests are on the same network
- * - Limiting multicast responses to 1 per second per resource record
- * - Fragmenting replies if required
- * - Subscribe to netif address/link change events and act on them (currently needs to be done manually)
- * - Handling multi-packet known answers
- * - Individual known answer detection for all local IPv6 addresses
- * - Dynamic size of outgoing packet
- */
-
-/*
- * Copyright (c) 2015 Verisure Innovation AB
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Erik Ekman <erik.ekman@verisure.com>
- *
- * Please coordinate changes and requests with Erik Ekman
- * <erik.ekman@verisure.com>
- *
- */
-
-#include "lwip/apps/mdns.h"
-#include "lwip/apps/mdns_priv.h"
-#include "lwip/netif.h"
-#include "lwip/udp.h"
-#include "lwip/ip_addr.h"
-#include "lwip/mem.h"
-#include "lwip/prot/dns.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#if LWIP_MDNS_RESPONDER
-
-#if (LWIP_IPV4 && !LWIP_IGMP)
-  #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h"
-#endif
-#if (LWIP_IPV6 && !LWIP_IPV6_MLD)
-#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP)
-  #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-
-#if LWIP_IPV4
-#include "lwip/igmp.h"
-/* IPv4 multicast group 224.0.0.251 */
-static const ip_addr_t v4group = IPADDR4_INIT(PP_HTONL(0xE00000FBUL));
-#endif
-
-#if LWIP_IPV6
-#include "lwip/mld6.h"
-/* IPv6 multicast group FF02::FB */
-static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x000000FBUL));
-#endif
-
-#define MDNS_PORT 5353
-#define MDNS_TTL  255
-
-/* Stored offsets to beginning of domain names
- * Used for compression.
- */
-#define NUM_DOMAIN_OFFSETS 10
-#define DOMAIN_JUMP_SIZE 2
-#define DOMAIN_JUMP 0xc000
-
-static u8_t mdns_netif_client_id;
-static struct udp_pcb *mdns_pcb;
-
-#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id))
-
-#define TOPDOMAIN_LOCAL "local"
-
-#define REVERSE_PTR_TOPDOMAIN "arpa"
-#define REVERSE_PTR_V4_DOMAIN "in-addr"
-#define REVERSE_PTR_V6_DOMAIN "ip6"
-
-#define SRV_PRIORITY 0
-#define SRV_WEIGHT   0
-
-/* Payload size allocated for each outgoing UDP packet */
-#define OUTPACKET_SIZE 500
-
-/* Lookup from hostname -> IPv4 */
-#define REPLY_HOST_A            0x01
-/* Lookup from IPv4/v6 -> hostname */
-#define REPLY_HOST_PTR_V4       0x02
-/* Lookup from hostname -> IPv6 */
-#define REPLY_HOST_AAAA         0x04
-/* Lookup from hostname -> IPv6 */
-#define REPLY_HOST_PTR_V6       0x08
-
-/* Lookup for service types */
-#define REPLY_SERVICE_TYPE_PTR  0x10
-/* Lookup for instances of service */
-#define REPLY_SERVICE_NAME_PTR  0x20
-/* Lookup for location of service instance */
-#define REPLY_SERVICE_SRV       0x40
-/* Lookup for text info on service instance */
-#define REPLY_SERVICE_TXT       0x80
-
-static const char *dnssd_protos[] = {
-    "_udp", /* DNSSD_PROTO_UDP */
-    "_tcp", /* DNSSD_PROTO_TCP */
-};
-
-/** Description of a service */
-struct mdns_service {
-  /** TXT record to answer with */
-  struct mdns_domain txtdata;
-  /** Name of service, like 'myweb' */
-  char name[MDNS_LABEL_MAXLEN + 1];
-  /** Type of service, like '_http' */
-  char service[MDNS_LABEL_MAXLEN + 1];
-  /** Callback function and userdata
-   * to update txtdata buffer */
-  service_get_txt_fn_t txt_fn;
-  void *txt_userdata;
-  /** TTL in seconds of SRV/TXT replies */
-  u32_t dns_ttl;
-  /** Protocol, TCP or UDP */
-  u16_t proto;
-  /** Port of the service */
-  u16_t port;
-};
-
-/** Description of a host/netif */
-struct mdns_host {
-  /** Hostname */
-  char name[MDNS_LABEL_MAXLEN + 1];
-  /** Pointer to services */
-  struct mdns_service *services[MDNS_MAX_SERVICES];
-  /** TTL in seconds of A/AAAA/PTR replies */
-  u32_t dns_ttl;
-};
-
-/** Information about received packet */
-struct mdns_packet {
-  /** Sender IP/port */
-  ip_addr_t source_addr;
-  u16_t source_port;
-  /** If packet was received unicast */
-  u16_t recv_unicast;
-  /** Netif that received the packet */
-  struct netif *netif;
-  /** Packet data */
-  struct pbuf *pbuf;
-  /** Current parsing offset in packet */
-  u16_t parse_offset;
-  /** Identifier. Used in legacy queries */
-  u16_t tx_id;
-  /** Number of questions in packet,
-   *  read from packet header */
-  u16_t questions;
-  /** Number of unparsed questions */
-  u16_t questions_left;
-  /** Number of answers in packet,
-   *  (sum of normal, authorative and additional answers)
-   *  read from packet header */
-  u16_t answers;
-  /** Number of unparsed answers */
-  u16_t answers_left;
-};
-
-/** Information about outgoing packet */
-struct mdns_outpacket {
-  /** Netif to send the packet on */
-  struct netif *netif;
-  /** Packet data */
-  struct pbuf *pbuf;
-  /** Current write offset in packet */
-  u16_t write_offset;
-  /** Identifier. Used in legacy queries */
-  u16_t tx_id;
-  /** Destination IP/port if sent unicast */
-  ip_addr_t dest_addr;
-  u16_t dest_port;
-  /** Number of questions written */
-  u16_t questions;
-  /** Number of normal answers written */
-  u16_t answers;
-  /** Number of additional answers written */
-  u16_t additional;
-  /** Offsets for written domain names in packet.
-   *  Used for compression */
-  u16_t domain_offsets[NUM_DOMAIN_OFFSETS];
-  /** If all answers in packet should set cache_flush bit */
-  u8_t cache_flush;
-  /** If reply should be sent unicast */
-  u8_t unicast_reply;
-  /** If legacy query. (tx_id needed, and write
-   *  question again in reply before answer) */
-  u8_t legacy_query;
-  /* Reply bitmask for host information */
-  u8_t host_replies;
-  /* Bitmask for which reverse IPv6 hosts to answer */
-  u8_t host_reverse_v6_replies;
-  /* Reply bitmask per service */
-  u8_t serv_replies[MDNS_MAX_SERVICES];
-};
-
-/** Domain, type and class.
- *  Shared between questions and answers */
-struct mdns_rr_info {
-  struct mdns_domain domain;
-  u16_t type;
-  u16_t klass;
-};
-
-struct mdns_question {
-  struct mdns_rr_info info;
-  /** unicast reply requested */
-  u16_t unicast;
-};
-
-struct mdns_answer {
-  struct mdns_rr_info info;
-  /** cache flush command bit */
-  u16_t cache_flush;
-  /* Validity time in seconds */
-  u32_t ttl;
-  /** Length of variable answer */
-  u16_t rd_length;
-  /** Offset of start of variable answer in packet */
-  u16_t rd_offset;
-};
-
-/**
- * Add a label part to a domain
- * @param domain The domain to add a label to
- * @param label The label to add, like &lt;hostname&gt;, 'local', 'com' or ''
- * @param len The length of the label
- * @return ERR_OK on success, an err_t otherwise if label too long
- */
-err_t
-mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len)
-{
-  if (len > MDNS_LABEL_MAXLEN) {
-    return ERR_VAL;
-  }
-  if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) {
-    return ERR_VAL;
-  }
-  /* Allow only zero marker on last byte */
-  if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) {
-    return ERR_VAL;
-  }
-  domain->name[domain->length] = len;
-  domain->length++;
-  if (len) {
-    MEMCPY(&domain->name[domain->length], label, len);
-    domain->length += len;
-  }
-  return ERR_OK;
-}
-
-/**
- * Internal readname function with max 6 levels of recursion following jumps
- * while decompressing name
- */
-static u16_t
-mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth)
-{
-  u8_t c;
-
-  do {
-    if (depth > 5) {
-      /* Too many jumps */
-      return MDNS_READNAME_ERROR;
-    }
-
-    c = pbuf_get_at(p, offset);
-    offset++;
-
-    /* is this a compressed label? */
-    if((c & 0xc0) == 0xc0) {
-      u16_t jumpaddr;
-      if (offset >= p->tot_len) {
-        /* Make sure both jump bytes fit in the packet */
-        return MDNS_READNAME_ERROR;
-      }
-      jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff));
-      offset++;
-      if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) {
-        u16_t res;
-      /* Recursive call, maximum depth will be checked */
-        res = mdns_readname_loop(p, jumpaddr, domain, depth + 1);
-        /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */
-        if (res == MDNS_READNAME_ERROR) {
-          return res;
-        }
-      } else {
-        return MDNS_READNAME_ERROR;
-      }
-      break;
-    }
-
-    /* normal label */
-    if (c <= MDNS_LABEL_MAXLEN) {
-      u8_t label[MDNS_LABEL_MAXLEN];
-      err_t res;
-
-      if (c + domain->length >= MDNS_DOMAIN_MAXLEN) {
-        return MDNS_READNAME_ERROR;
-      }
-      if (c != 0) {
-        if (pbuf_copy_partial(p, label, c, offset) != c) {
-          return MDNS_READNAME_ERROR;
-        }
-        offset += c;
-      }
-      res = mdns_domain_add_label(domain, (char *) label, c);
-      if (res != ERR_OK) {
-        return MDNS_READNAME_ERROR;
-      }
-    } else {
-      /* bad length byte */
-      return MDNS_READNAME_ERROR;
-    }
-  } while (c != 0);
-
-  return offset;
-}
-
-/**
- * Read possibly compressed domain name from packet buffer
- * @param p The packet
- * @param offset start position of domain name in packet
- * @param domain The domain name destination
- * @return The new offset after the domain, or MDNS_READNAME_ERROR
- *         if reading failed
- */
-u16_t
-mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain)
-{
-  memset(domain, 0, sizeof(struct mdns_domain));
-  return mdns_readname_loop(p, offset, domain, 0);
-}
-
-/**
- * Print domain name to debug output
- * @param domain The domain name
- */
-static void
-mdns_domain_debug_print(struct mdns_domain *domain)
-{
-  u8_t *src = domain->name;
-  u8_t i;
-
-  while (*src) {
-    u8_t label_len = *src;
-    src++;
-    for (i = 0; i < label_len; i++) {
-      LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i]));
-    }
-    src += label_len;
-    LWIP_DEBUGF(MDNS_DEBUG, ("."));
-  }
-}
-
-/**
- * Return 1 if contents of domains match (case-insensitive)
- * @param a Domain name to compare 1
- * @param b Domain name to compare 2
- * @return 1 if domains are equal ignoring case, 0 otherwise
- */
-int
-mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b)
-{
-  u8_t *ptra, *ptrb;
-  u8_t len;
-  int res;
-
-  if (a->length != b->length) {
-    return 0;
-  }
-
-  ptra = a->name;
-  ptrb = b->name;
-  while (*ptra && *ptrb && ptra < &a->name[a->length]) {
-    if (*ptra != *ptrb) {
-      return 0;
-    }
-    len = *ptra;
-    ptra++;
-    ptrb++;
-    res = lwip_strnicmp((char *) ptra, (char *) ptrb, len);
-    if (res != 0) {
-      return 0;
-    }
-    ptra += len;
-    ptrb += len;
-  }
-  if (*ptra != *ptrb && ptra < &a->name[a->length]) {
-    return 0;
-  }
-  return 1;
-}
-
-/**
- * Call user supplied function to setup TXT data
- * @param service The service to build TXT record for
- */
-static void
-mdns_prepare_txtdata(struct mdns_service *service)
-{
-  memset(&service->txtdata, 0, sizeof(struct mdns_domain));
-  if (service->txt_fn) {
-    service->txt_fn(service, service->txt_userdata);
-  }
-}
-
-#if LWIP_IPV4
-/**
- * Build domain for reverse lookup of IPv4 address
- * like 12.0.168.192.in-addr.arpa. for 192.168.0.12
- * @param domain Where to write the domain name
- * @param addr Pointer to an IPv4 address to encode
- * @return ERR_OK if domain was written, an err_t otherwise
- */
-static err_t
-mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr)
-{
-  int i;
-  err_t res;
-  const u8_t *ptr;
-  if (!domain || !addr) {
-    return ERR_ARG;
-  }
-  memset(domain, 0, sizeof(struct mdns_domain));
-  ptr = (const u8_t *) addr;
-  for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) {
-    char buf[4];
-    u8_t val = ptr[i];
-
-    lwip_itoa(buf, sizeof(buf), val);
-    res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf));
-    LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res);
-  }
-  res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1));
-  LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1));
-  LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, NULL, 0);
-  LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res);
-
-  return ERR_OK;
-}
-#endif
-
-#if LWIP_IPV6
-/**
- * Build domain for reverse lookup of IP address
- * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab
- * @param domain Where to write the domain name
- * @param addr Pointer to an IPv6 address to encode
- * @return ERR_OK if domain was written, an err_t otherwise
- */
-static err_t
-mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr)
-{
-  int i;
-  err_t res;
-  const u8_t *ptr;
-  if (!domain || !addr) {
-    return ERR_ARG;
-  }
-  memset(domain, 0, sizeof(struct mdns_domain));
-  ptr = (const u8_t *) addr;
-  for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) {
-    char buf;
-    u8_t byte = ptr[i];
-    int j;
-    for (j = 0; j < 2; j++) {
-      if ((byte & 0x0F) < 0xA) {
-        buf = '0' + (byte & 0x0F);
-      } else {
-        buf = 'a' + (byte & 0x0F) - 0xA;
-      }
-      res = mdns_domain_add_label(domain, &buf, sizeof(buf));
-      LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res);
-      byte >>= 4;
-    }
-  }
-  res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1));
-  LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1));
-  LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, NULL, 0);
-  LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res);
-
-  return ERR_OK;
-}
-#endif
-
-/* Add .local. to domain */
-static err_t
-mdns_add_dotlocal(struct mdns_domain *domain)
-{
-  err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1));
-  LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res);
-  return mdns_domain_add_label(domain, NULL, 0);
-}
-
-/**
- * Build the <hostname>.local. domain name
- * @param domain Where to write the domain name
- * @param mdns TMDNS netif descriptor.
- * @return ERR_OK if domain <hostname>.local. was written, an err_t otherwise
- */
-static err_t
-mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns)
-{
-  err_t res;
-  memset(domain, 0, sizeof(struct mdns_domain));
-  LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL);
-  res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name));
-  LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res);
-  return mdns_add_dotlocal(domain);
-}
-
-/**
- * Build the lookup-all-services special DNS-SD domain name
- * @param domain Where to write the domain name
- * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise
- */
-static err_t
-mdns_build_dnssd_domain(struct mdns_domain *domain)
-{
-  err_t res;
-  memset(domain, 0, sizeof(struct mdns_domain));
-  res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1));
-  LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1));
-  LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
-  LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
-  return mdns_add_dotlocal(domain);
-}
-
-/**
- * Build domain name for a service
- * @param domain Where to write the domain name
- * @param service The service struct, containing service name, type and protocol
- * @param include_name Whether to include the service name in the domain
- * @return ERR_OK if domain was written. If service name is included,
- *         <name>.<type>.<proto>.local. will be written, otherwise <type>.<proto>.local.
- *         An err_t is returned on error.
- */
-static err_t
-mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name)
-{
-  err_t res;
-  memset(domain, 0, sizeof(struct mdns_domain));
-  if (include_name) {
-    res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name));
-    LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
-  }
-  res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service));
-  LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
-  LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
-  return mdns_add_dotlocal(domain);
-}
-
-/**
- * Check which replies we should send for a host/netif based on question
- * @param netif The network interface that received the question
- * @param rr Domain/type/class from a question
- * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for
- *                         if reply bit has REPLY_HOST_PTR_V6 set
- * @return Bitmask of which replies to send
- */
-static int
-check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply)
-{
-  err_t res;
-  int replies = 0;
-  struct mdns_domain mydomain;
-
-  LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */
-
-  if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) {
-    /* Invalid class */
-    return replies;
-  }
-
-  /* Handle PTR for our addresses */
-  if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) {
-#if LWIP_IPV6
-    int i;
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
-        res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i));
-        if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
-          replies |= REPLY_HOST_PTR_V6;
-          /* Mark which addresses where requested */
-          if (reverse_v6_reply) {
-            *reverse_v6_reply |= (1 << i);
-          }
-        }
-      }
-    }
-#endif
-#if LWIP_IPV4
-    if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
-      res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif));
-      if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
-        replies |= REPLY_HOST_PTR_V4;
-      }
-    }
-#endif
-  }
-
-  res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif));
-  /* Handle requests for our hostname */
-  if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
-    /* TODO return NSEC if unsupported protocol requested */
-#if LWIP_IPV4
-    if (!ip4_addr_isany_val(*netif_ip4_addr(netif))
-        && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) {
-      replies |= REPLY_HOST_A;
-    }
-#endif
-#if LWIP_IPV6
-    if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) {
-      replies |= REPLY_HOST_AAAA;
-    }
-#endif
-  }
-
-  return replies;
-}
-
-/**
- * Check which replies we should send for a service based on question
- * @param service A registered MDNS service
- * @param rr Domain/type/class from a question
- * @return Bitmask of which replies to send
- */
-static int
-check_service(struct mdns_service *service, struct mdns_rr_info *rr)
-{
-  err_t res;
-  int replies = 0;
-  struct mdns_domain mydomain;
-
-  if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) {
-    /* Invalid class */
-    return 0;
-  }
-
-  res = mdns_build_dnssd_domain(&mydomain);
-  if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
-      (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) {
-    /* Request for all service types */
-    replies |= REPLY_SERVICE_TYPE_PTR;
-  }
-
-  res = mdns_build_service_domain(&mydomain, service, 0);
-  if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
-      (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) {
-    /* Request for the instance of my service */
-    replies |= REPLY_SERVICE_NAME_PTR;
-  }
-
-  res = mdns_build_service_domain(&mydomain, service, 1);
-  if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
-    /* Request for info about my service */
-    if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) {
-      replies |= REPLY_SERVICE_SRV;
-    }
-    if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) {
-      replies |= REPLY_SERVICE_TXT;
-    }
-  }
-
-  return replies;
-}
-
-/**
- * Return bytes needed to write before jump for best result of compressing supplied domain
- * against domain in outpacket starting at specified offset.
- * If a match is found, offset is updated to where to jump to
- * @param pbuf Pointer to pbuf with the partially constructed DNS packet
- * @param offset Start position of a domain written earlier. If this location is suitable
- *               for compression, the pointer is updated to where in the domain to jump to.
- * @param domain The domain to write
- * @return Number of bytes to write of the new domain before writing a jump to the offset.
- *         If compression can not be done against this previous domain name, the full new
- *         domain length is returned.
- */
-u16_t
-mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain)
-{
-  struct mdns_domain target;
-  u16_t target_end;
-  u8_t target_len;
-  u8_t writelen = 0;
-  u8_t *ptr;
-  if (pbuf == NULL) {
-    return domain->length;
-  }
-  target_end = mdns_readname(pbuf, *offset, &target);
-  if (target_end == MDNS_READNAME_ERROR) {
-    return domain->length;
-  }
-  target_len = (u8_t)(target_end - *offset);
-  ptr = domain->name;
-  while (writelen < domain->length) {
-    u8_t domainlen = (u8_t)(domain->length - writelen);
-    u8_t labellen;
-    if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) {
-      /* Compare domains if target is long enough, and we have enough left of the domain */
-      u8_t targetpos = (u8_t)(target.length - domainlen);
-      if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) {
-        /* We are checking at or beyond a jump in the original, stop looking */
-        break;
-      }
-      if (target.length >= domainlen &&
-          memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) {
-        *offset += targetpos;
-        return writelen;
-      }
-    }
-    /* Skip to next label in domain */
-    labellen = *ptr;
-    writelen += 1 + labellen;
-    ptr += 1 + labellen;
-  }
-  /* Nothing found */
-  return domain->length;
-}
-
-/**
- * Write domain to outpacket. Compression will be attempted,
- * unless domain->skip_compression is set.
- * @param outpkt The outpacket to write to
- * @param domain The domain name to write
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain)
-{
-  int i;
-  err_t res;
-  u16_t writelen = domain->length;
-  u16_t jump_offset = 0;
-  u16_t jump;
-
-  if (!domain->skip_compression) {
-    for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) {
-      u16_t offset = outpkt->domain_offsets[i];
-      if (offset) {
-        u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain);
-        if (len < writelen) {
-          writelen = len;
-          jump_offset = offset;
-        }
-      }
-    }
-  }
-
-  if (writelen) {
-    /* Write uncompressed part of name */
-    res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset);
-    if (res != ERR_OK) {
-      return res;
-    }
-
-    /* Store offset of this new domain */
-    for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) {
-      if (outpkt->domain_offsets[i] == 0) {
-        outpkt->domain_offsets[i] = outpkt->write_offset;
-        break;
-      }
-    }
-
-    outpkt->write_offset += writelen;
-  }
-  if (jump_offset) {
-    /* Write jump */
-    jump = lwip_htons(DOMAIN_JUMP | jump_offset);
-    res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset);
-    if (res != ERR_OK) {
-      return res;
-    }
-    outpkt->write_offset += DOMAIN_JUMP_SIZE;
-  }
-  return ERR_OK;
-}
-
-/**
- * Write a question to an outpacket
- * A question contains domain, type and class. Since an answer also starts with these fields this function is also
- * called from mdns_add_answer().
- * @param outpkt The outpacket to write to
- * @param domain The domain name the answer is for
- * @param type The DNS type of the answer (like 'AAAA', 'SRV')
- * @param klass The DNS type of the answer (like 'IN')
- * @param unicast If highest bit in class should be set, to instruct the responder to
- *                reply with a unicast packet
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast)
-{
-  u16_t question_len;
-  u16_t field16;
-  err_t res;
-
-  if (!outpkt->pbuf) {
-    /* If no pbuf is active, allocate one */
-    outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM);
-    if (!outpkt->pbuf) {
-      return ERR_MEM;
-    }
-    outpkt->write_offset = SIZEOF_DNS_HDR;
-  }
-
-  /* Worst case calculation. Domain string might be compressed */
-  question_len = domain->length + sizeof(type) + sizeof(klass);
-  if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) {
-    /* No space */
-    return ERR_MEM;
-  }
-
-  /* Write name */
-  res = mdns_write_domain(outpkt, domain);
-  if (res != ERR_OK) {
-    return res;
-  }
-
-  /* Write type */
-  field16 = lwip_htons(type);
-  res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
-  if (res != ERR_OK) {
-    return res;
-  }
-  outpkt->write_offset += sizeof(field16);
-
-  /* Write class */
-  if (unicast) {
-    klass |= 0x8000;
-  }
-  field16 = lwip_htons(klass);
-  res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
-  if (res != ERR_OK) {
-    return res;
-  }
-  outpkt->write_offset += sizeof(field16);
-
-  return ERR_OK;
-}
-
-/**
- * Write answer to reply packet.
- * buf or answer_domain can be null. The rd_length written will be buf_length +
- * size of (compressed) domain. Most uses will need either buf or answer_domain,
- * special case is SRV that starts with 3 u16 and then a domain name.
- * @param reply The outpacket to write to
- * @param domain The domain name the answer is for
- * @param type The DNS type of the answer (like 'AAAA', 'SRV')
- * @param klass The DNS type of the answer (like 'IN')
- * @param cache_flush If highest bit in class should be set, to instruct receiver that
- *                    this reply replaces any earlier answer for this domain/type/class
- * @param ttl Validity time in seconds to send out for IP address data in DNS replies
- * @param buf Pointer to buffer of answer data
- * @param buf_length Length of variable data
- * @param answer_domain A domain to write after any buffer data as answer
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush,
-                u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain)
-{
-  u16_t answer_len;
-  u16_t field16;
-  u16_t rdlen_offset;
-  u16_t answer_offset;
-  u32_t field32;
-  err_t res;
-
-  if (!reply->pbuf) {
-    /* If no pbuf is active, allocate one */
-    reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM);
-    if (!reply->pbuf) {
-      return ERR_MEM;
-    }
-    reply->write_offset = SIZEOF_DNS_HDR;
-  }
-
-  /* Worst case calculation. Domain strings might be compressed */
-  answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/;
-  if (buf) {
-    answer_len += (u16_t)buf_length;
-  }
-  if (answer_domain) {
-    answer_len += answer_domain->length;
-  }
-  if (reply->write_offset + answer_len > reply->pbuf->tot_len) {
-    /* No space */
-    return ERR_MEM;
-  }
-
-  /* Answer starts with same data as question, then more fields */
-  mdns_add_question(reply, domain, type, klass, cache_flush);
-
-  /* Write TTL */
-  field32 = lwip_htonl(ttl);
-  res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset);
-  if (res != ERR_OK) {
-    return res;
-  }
-  reply->write_offset += sizeof(field32);
-
-  /* Store offsets and skip forward to the data */
-  rdlen_offset = reply->write_offset;
-  reply->write_offset += sizeof(field16);
-  answer_offset = reply->write_offset;
-
-  if (buf) {
-    /* Write static data */
-    res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset);
-    if (res != ERR_OK) {
-      return res;
-    }
-    reply->write_offset += (u16_t)buf_length;
-  }
-
-  if (answer_domain) {
-    /* Write name answer (compressed if possible) */
-    res = mdns_write_domain(reply, answer_domain);
-    if (res != ERR_OK) {
-      return res;
-    }
-  }
-
-  /* Write rd_length after when we know the answer size */
-  field16 = lwip_htons(reply->write_offset - answer_offset);
-  res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset);
-
-  return res;
-}
-
-/**
- * Helper function for mdns_read_question/mdns_read_answer
- * Reads a domain, type and class from the packet
- * @param pkt The MDNS packet to read from. The parse_offset field will be
- *            incremented to point to the next unparsed byte.
- * @param info The struct to fill with domain, type and class
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info)
-{
-  u16_t field16, copied;
-  pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain);
-  if (pkt->parse_offset == MDNS_READNAME_ERROR) {
-    return ERR_VAL;
-  }
-
-  copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
-  if (copied != sizeof(field16)) {
-    return ERR_VAL;
-  }
-  pkt->parse_offset += copied;
-  info->type = lwip_ntohs(field16);
-
-  copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
-  if (copied != sizeof(field16)) {
-    return ERR_VAL;
-  }
-  pkt->parse_offset += copied;
-  info->klass = lwip_ntohs(field16);
-
-  return ERR_OK;
-}
-
-/**
- * Read a question from the packet.
- * All questions have to be read before the answers.
- * @param pkt The MDNS packet to read from. The questions_left field will be decremented
- *            and the parse_offset will be updated.
- * @param question The struct to fill with question data
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question)
-{
-  /* Safety check */
-  if (pkt->pbuf->tot_len < pkt->parse_offset) {
-    return ERR_VAL;
-  }
-
-  if (pkt->questions_left) {
-    err_t res;
-    pkt->questions_left--;
-
-    memset(question, 0, sizeof(struct mdns_question));
-    res = mdns_read_rr_info(pkt, &question->info);
-    if (res != ERR_OK) {
-      return res;
-    }
-
-    /* Extract unicast flag from class field */
-    question->unicast = question->info.klass & 0x8000;
-    question->info.klass &= 0x7FFF;
-
-    return ERR_OK;
-  }
-  return ERR_VAL;
-}
-
-/**
- * Read an answer from the packet
- * The variable length reply is not copied, its pbuf offset and length is stored instead.
- * @param pkt The MDNS packet to read. The answers_left field will be decremented and
- *            the parse_offset will be updated.
- * @param answer The struct to fill with answer data
- * @return ERR_OK on success, an err_t otherwise
- */
-static err_t
-mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer)
-{
-  /* Read questions first */
-  if (pkt->questions_left) {
-    return ERR_VAL;
-  }
-
-  /* Safety check */
-  if (pkt->pbuf->tot_len < pkt->parse_offset) {
-    return ERR_VAL;
-  }
-
-  if (pkt->answers_left) {
-    u16_t copied, field16;
-    u32_t ttl;
-    err_t res;
-    pkt->answers_left--;
-
-    memset(answer, 0, sizeof(struct mdns_answer));
-    res = mdns_read_rr_info(pkt, &answer->info);
-    if (res != ERR_OK) {
-      return res;
-    }
-
-    /* Extract cache_flush flag from class field */
-    answer->cache_flush = answer->info.klass & 0x8000;
-    answer->info.klass &= 0x7FFF;
-
-    copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset);
-    if (copied != sizeof(ttl)) {
-      return ERR_VAL;
-    }
-    pkt->parse_offset += copied;
-    answer->ttl = lwip_ntohl(ttl);
-
-    copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
-    if (copied != sizeof(field16)) {
-      return ERR_VAL;
-    }
-    pkt->parse_offset += copied;
-    answer->rd_length = lwip_ntohs(field16);
-
-    answer->rd_offset = pkt->parse_offset;
-    pkt->parse_offset += answer->rd_length;
-
-    return ERR_OK;
-  }
-  return ERR_VAL;
-}
-
-#if LWIP_IPV4
-/** Write an IPv4 address (A) RR to outpacket */
-static err_t
-mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif)
-{
-  struct mdns_domain host;
-  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n"));
-  return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL);
-}
-
-/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */
-static err_t
-mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif)
-{
-  struct mdns_domain host, revhost;
-  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
-  mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif));
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n"));
-  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host);
-}
-#endif
-
-#if LWIP_IPV6
-/** Write an IPv6 address (AAAA) RR to outpacket */
-static err_t
-mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex)
-{
-  struct mdns_domain host;
-  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n"));
-  return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL);
-}
-
-/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */
-static err_t
-mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex)
-{
-  struct mdns_domain host, revhost;
-  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
-  mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex));
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n"));
-  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host);
-}
-#endif
-
-/** Write an all-services -> servicetype PTR RR to outpacket */
-static err_t
-mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service)
-{
-  struct mdns_domain service_type, service_dnssd;
-  mdns_build_service_domain(&service_type, service, 0);
-  mdns_build_dnssd_domain(&service_dnssd);
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n"));
-  return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type);
-}
-
-/** Write a servicetype -> servicename PTR RR to outpacket */
-static err_t
-mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service)
-{
-  struct mdns_domain service_type, service_instance;
-  mdns_build_service_domain(&service_type, service, 0);
-  mdns_build_service_domain(&service_instance, service, 1);
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n"));
-  return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance);
-}
-
-/** Write a SRV RR to outpacket */
-static err_t
-mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service)
-{
-  struct mdns_domain service_instance, srvhost;
-  u16_t srvdata[3];
-  mdns_build_service_domain(&service_instance, service, 1);
-  mdns_build_host_domain(&srvhost, mdns);
-  if (reply->legacy_query) {
-    /* RFC 6762 section 18.14:
-     * In legacy unicast responses generated to answer legacy queries,
-     * name compression MUST NOT be performed on SRV records.
-     */
-    srvhost.skip_compression = 1;
-  }
-  srvdata[0] = lwip_htons(SRV_PRIORITY);
-  srvdata[1] = lwip_htons(SRV_WEIGHT);
-  srvdata[2] = lwip_htons(service->port);
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n"));
-  return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl,
-                         (const u8_t *) &srvdata, sizeof(srvdata), &srvhost);
-}
-
-/** Write a TXT RR to outpacket */
-static err_t
-mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service)
-{
-  struct mdns_domain service_instance;
-  mdns_build_service_domain(&service_instance, service, 1);
-  mdns_prepare_txtdata(service);
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n"));
-  return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl,
-                         (u8_t *) &service->txtdata.name, service->txtdata.length, NULL);
-}
-
-/**
- * Setup outpacket as a reply to the incoming packet
- */
-static void
-mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in)
-{
-  memset(out, 0, sizeof(struct mdns_outpacket));
-  out->cache_flush = 1;
-  out->netif = in->netif;
-
-  /* Copy source IP/port to use when responding unicast, or to choose
-   * which pcb to use for multicast (IPv4/IPv6)
-   */
-  SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t));
-  out->dest_port = in->source_port;
-
-  if (in->source_port != MDNS_PORT) {
-    out->unicast_reply = 1;
-    out->cache_flush = 0;
-    if (in->questions == 1) {
-      out->legacy_query = 1;
-      out->tx_id = in->tx_id;
-    }
-  }
-
-  if (in->recv_unicast) {
-    out->unicast_reply = 1;
-  }
-}
-
-/**
- * Send chosen answers as a reply
- *
- * Add all selected answers (first write will allocate pbuf)
- * Add additional answers based on the selected answers
- * Send the packet
- */
-static void
-mdns_send_outpacket(struct mdns_outpacket *outpkt)
-{
-  struct mdns_service *service;
-  err_t res;
-  int i;
-  struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif);
-
-  /* Write answers to host questions */
-#if LWIP_IPV4
-  if (outpkt->host_replies & REPLY_HOST_A) {
-    res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif);
-    if (res != ERR_OK) {
-      goto cleanup;
-    }
-    outpkt->answers++;
-  }
-  if (outpkt->host_replies & REPLY_HOST_PTR_V4) {
-    res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif);
-    if (res != ERR_OK) {
-      goto cleanup;
-    }
-    outpkt->answers++;
-  }
-#endif
-#if LWIP_IPV6
-  if (outpkt->host_replies & REPLY_HOST_AAAA) {
-    int addrindex;
-    for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) {
-        res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex);
-        if (res != ERR_OK) {
-          goto cleanup;
-        }
-        outpkt->answers++;
-      }
-    }
-  }
-  if (outpkt->host_replies & REPLY_HOST_PTR_V6) {
-    u8_t rev_addrs = outpkt->host_reverse_v6_replies;
-    int addrindex = 0;
-    while (rev_addrs) {
-      if (rev_addrs & 1) {
-        res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex);
-        if (res != ERR_OK) {
-          goto cleanup;
-        }
-        outpkt->answers++;
-      }
-      addrindex++;
-      rev_addrs >>= 1;
-    }
-  }
-#endif
-
-  /* Write answers to service questions */
-  for (i = 0; i < MDNS_MAX_SERVICES; ++i) {
-    service = mdns->services[i];
-    if (!service) {
-      continue;
-    }
-
-    if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) {
-      res = mdns_add_servicetype_ptr_answer(outpkt, service);
-      if (res != ERR_OK) {
-        goto cleanup;
-      }
-      outpkt->answers++;
-    }
-
-    if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) {
-      res = mdns_add_servicename_ptr_answer(outpkt, service);
-      if (res != ERR_OK) {
-        goto cleanup;
-      }
-      outpkt->answers++;
-    }
-
-    if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) {
-      res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service);
-      if (res != ERR_OK) {
-        goto cleanup;
-      }
-      outpkt->answers++;
-    }
-
-    if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) {
-      res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service);
-      if (res != ERR_OK) {
-        goto cleanup;
-      }
-      outpkt->answers++;
-    }
-  }
-
-  /* All answers written, add additional RRs */
-  for (i = 0; i < MDNS_MAX_SERVICES; ++i) {
-    service = mdns->services[i];
-    if (!service) {
-      continue;
-    }
-
-    if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) {
-      /* Our service instance requested, include SRV & TXT
-       * if they are already not requested. */
-      if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) {
-        res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service);
-        if (res != ERR_OK) {
-          goto cleanup;
-        }
-        outpkt->additional++;
-      }
-
-      if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) {
-        res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service);
-        if (res != ERR_OK) {
-          goto cleanup;
-        }
-        outpkt->additional++;
-      }
-    }
-
-    /* If service instance, SRV, record or an IP address is requested,
-     * supply all addresses for the host
-     */
-    if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) ||
-        (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) {
-#if LWIP_IPV6
-      if (!(outpkt->host_replies & REPLY_HOST_AAAA)) {
-        int addrindex;
-        for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) {
-          if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) {
-            res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex);
-            if (res != ERR_OK) {
-              goto cleanup;
-            }
-            outpkt->additional++;
-          }
-        }
-      }
-#endif
-#if LWIP_IPV4
-      if (!(outpkt->host_replies & REPLY_HOST_A)) {
-        res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif);
-        if (res != ERR_OK) {
-          goto cleanup;
-        }
-        outpkt->additional++;
-      }
-#endif
-    }
-  }
-
-  if (outpkt->pbuf) {
-    const ip_addr_t *mcast_destaddr;
-    struct dns_hdr hdr;
-
-    /* Write header */
-    memset(&hdr, 0, sizeof(hdr));
-    hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
-    hdr.numanswers = lwip_htons(outpkt->answers);
-    hdr.numextrarr = lwip_htons(outpkt->additional);
-    if (outpkt->legacy_query) {
-      hdr.numquestions = lwip_htons(1);
-      hdr.id = lwip_htons(outpkt->tx_id);
-    }
-    pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr));
-
-    /* Shrink packet */
-    pbuf_realloc(outpkt->pbuf, outpkt->write_offset);
-
-    if (IP_IS_V6_VAL(outpkt->dest_addr)) {
-#if LWIP_IPV6
-      mcast_destaddr = &v6group;
-#endif
-    } else {
-#if LWIP_IPV4
-      mcast_destaddr = &v4group;
-#endif
-    }
-    /* Send created packet */
-    LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply));
-    if (outpkt->unicast_reply) {
-      udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif);
-    } else {
-      udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif);
-    }
-  }
-
-cleanup:
-  if (outpkt->pbuf) {
-    pbuf_free(outpkt->pbuf);
-    outpkt->pbuf = NULL;
-  }
-}
-
-/**
- * Send unsolicited answer containing all our known data
- * @param netif The network interface to send on
- * @param destination The target address to send to (usually multicast address)
- */
-static void
-mdns_announce(struct netif *netif, const ip_addr_t *destination)
-{
-  struct mdns_outpacket announce;
-  int i;
-  struct mdns_host* mdns = NETIF_TO_HOST(netif);
-
-  memset(&announce, 0, sizeof(announce));
-  announce.netif = netif;
-  announce.cache_flush = 1;
-#if LWIP_IPV4
-  if (!ip4_addr_isany_val(*netif_ip4_addr(netif)))
-    announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4;
-#endif
-#if LWIP_IPV6
-  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
-    if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
-      announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6;
-      announce.host_reverse_v6_replies |= (1 << i);
-    }
-  }
-#endif
-
-  for (i = 0; i < MDNS_MAX_SERVICES; i++) {
-    struct mdns_service *serv = mdns->services[i];
-    if (serv) {
-      announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR |
-          REPLY_SERVICE_SRV | REPLY_SERVICE_TXT;
-    }
-  }
-
-  announce.dest_port = MDNS_PORT;
-  SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr));
-  mdns_send_outpacket(&announce);
-}
-
-/**
- * Handle question MDNS packet
- * 1. Parse all questions and set bits what answers to send
- * 2. Clear pending answers if known answers are supplied
- * 3. Put chosen answers in new packet and send as reply
- */
-static void
-mdns_handle_question(struct mdns_packet *pkt)
-{
-  struct mdns_service *service;
-  struct mdns_outpacket reply;
-  int replies = 0;
-  int i;
-  err_t res;
-  struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif);
-
-  mdns_init_outpacket(&reply, pkt);
-
-  while (pkt->questions_left) {
-    struct mdns_question q;
-
-    res = mdns_read_question(pkt, &q);
-    if (res != ERR_OK) {
-      LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n"));
-      return;
-    }
-
-    LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain "));
-    mdns_domain_debug_print(&q.info.domain);
-    LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass));
-
-    if (q.unicast) {
-      /* Reply unicast if any question is unicast */
-      reply.unicast_reply = 1;
-    }
-
-    reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies);
-    replies |= reply.host_replies;
-
-    for (i = 0; i < MDNS_MAX_SERVICES; ++i) {
-      service = mdns->services[i];
-      if (!service) {
-        continue;
-      }
-      reply.serv_replies[i] |= check_service(service, &q.info);
-      replies |= reply.serv_replies[i];
-    }
-
-    if (replies && reply.legacy_query) {
-      /* Add question to reply packet (legacy packet only has 1 question) */
-      res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0);
-      if (res != ERR_OK) {
-        goto cleanup;
-      }
-    }
-  }
-
-  /* Handle known answers */
-  while (pkt->answers_left) {
-    struct mdns_answer ans;
-    u8_t rev_v6;
-    int match;
-
-    res = mdns_read_answer(pkt, &ans);
-    if (res != ERR_OK) {
-      LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n"));
-      goto cleanup;
-    }
-
-    LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain "));
-    mdns_domain_debug_print(&ans.info.domain);
-    LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
-
-
-    if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) {
-      /* Skip known answers for ANY type & class */
-      continue;
-    }
-
-    rev_v6 = 0;
-    match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6);
-    if (match && (ans.ttl > (mdns->dns_ttl / 2))) {
-      /* The RR in the known answer matches an RR we are planning to send,
-       * and the TTL is less than half gone.
-       * If the payload matches we should not send that answer.
-       */
-      if (ans.info.type == DNS_RRTYPE_PTR) {
-        /* Read domain and compare */
-        struct mdns_domain known_ans, my_ans;
-        u16_t len;
-        len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
-        res = mdns_build_host_domain(&my_ans, mdns);
-        if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
-#if LWIP_IPV4
-          if (match & REPLY_HOST_PTR_V4) {
-              LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n"));
-              reply.host_replies &= ~REPLY_HOST_PTR_V4;
-          }
-#endif
-#if LWIP_IPV6
-          if (match & REPLY_HOST_PTR_V6) {
-              LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n"));
-              reply.host_reverse_v6_replies &= ~rev_v6;
-              if (reply.host_reverse_v6_replies == 0) {
-                reply.host_replies &= ~REPLY_HOST_PTR_V6;
-              }
-          }
-#endif
-        }
-      } else if (match & REPLY_HOST_A) {
-#if LWIP_IPV4
-        if (ans.rd_length == sizeof(ip4_addr_t) &&
-            pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) {
-          LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n"));
-          reply.host_replies &= ~REPLY_HOST_A;
-        }
-#endif
-      } else if (match & REPLY_HOST_AAAA) {
-#if LWIP_IPV6
-        if (ans.rd_length == sizeof(ip6_addr_t) &&
-            /* TODO this clears all AAAA responses if first addr is set as known */
-            pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) {
-          LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n"));
-          reply.host_replies &= ~REPLY_HOST_AAAA;
-        }
-#endif
-      }
-    }
-
-    for (i = 0; i < MDNS_MAX_SERVICES; ++i) {
-      service = mdns->services[i];
-      if (!service) {
-        continue;
-      }
-      match = reply.serv_replies[i] & check_service(service, &ans.info);
-      if (match && (ans.ttl > (service->dns_ttl / 2))) {
-        /* The RR in the known answer matches an RR we are planning to send,
-         * and the TTL is less than half gone.
-         * If the payload matches we should not send that answer.
-         */
-        if (ans.info.type == DNS_RRTYPE_PTR) {
-          /* Read domain and compare */
-          struct mdns_domain known_ans, my_ans;
-          u16_t len;
-          len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
-          if (len != MDNS_READNAME_ERROR) {
-            if (match & REPLY_SERVICE_TYPE_PTR) {
-              res = mdns_build_service_domain(&my_ans, service, 0);
-              if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
-                LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n"));
-                reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR;
-              }
-            }
-            if (match & REPLY_SERVICE_NAME_PTR) {
-              res = mdns_build_service_domain(&my_ans, service, 1);
-              if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
-                LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n"));
-                reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR;
-              }
-            }
-          }
-        } else if (match & REPLY_SERVICE_SRV) {
-          /* Read and compare to my SRV record */
-          u16_t field16, len, read_pos;
-          struct mdns_domain known_ans, my_ans;
-          read_pos = ans.rd_offset;
-          do {
-            /* Check priority field */
-            len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) {
-              break;
-            }
-            read_pos += len;
-            /* Check weight field */
-            len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) {
-              break;
-            }
-            read_pos += len;
-            /* Check port field */
-            len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) {
-              break;
-            }
-            read_pos += len;
-            /* Check host field */
-            len = mdns_readname(pkt->pbuf, read_pos, &known_ans);
-            mdns_build_host_domain(&my_ans, mdns);
-            if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) {
-              break;
-            }
-            LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n"));
-            reply.serv_replies[i] &= ~REPLY_SERVICE_SRV;
-          } while (0);
-        } else if (match & REPLY_SERVICE_TXT) {
-          mdns_prepare_txtdata(service);
-          if (service->txtdata.length == ans.rd_length &&
-              pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
-            LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n"));
-            reply.serv_replies[i] &= ~REPLY_SERVICE_TXT;
-          }
-        }
-      }
-    }
-  }
-
-  mdns_send_outpacket(&reply);
-
-cleanup:
-  if (reply.pbuf) {
-    /* This should only happen if we fail to alloc/write question for legacy query */
-    pbuf_free(reply.pbuf);
-    reply.pbuf = NULL;
-  }
-}
-
-/**
- * Handle response MDNS packet
- * Only prints debug for now. Will need more code to do conflict resolution.
- */
-static void
-mdns_handle_response(struct mdns_packet *pkt)
-{
-  /* Ignore all questions */
-  while (pkt->questions_left) {
-    struct mdns_question q;
-    err_t res;
-
-    res = mdns_read_question(pkt, &q);
-    if (res != ERR_OK) {
-      LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n"));
-      return;
-    }
-  }
-
-  while (pkt->answers_left) {
-    struct mdns_answer ans;
-    err_t res;
-
-    res = mdns_read_answer(pkt, &ans);
-    if (res != ERR_OK) {
-      LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n"));
-      return;
-    }
-
-    LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain "));
-    mdns_domain_debug_print(&ans.info.domain);
-    LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
-  }
-}
-
-/**
- * Receive input function for MDNS packets.
- * Handles both IPv4 and IPv6 UDP pcbs.
- */
-static void
-mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
-{
-  struct dns_hdr hdr;
-  struct mdns_packet packet;
-  struct netif *recv_netif = ip_current_input_netif();
-  u16_t offset = 0;
-
-  LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(pcb);
-
-  LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len));
-
-  if (NETIF_TO_HOST(recv_netif) == NULL) {
-    /* From netif not configured for MDNS */
-    goto dealloc;
-  }
-
-  if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) {
-    /* Too small */
-    goto dealloc;
-  }
-  offset += SIZEOF_DNS_HDR;
-
-  if (DNS_HDR_GET_OPCODE(&hdr)) {
-    /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */
-    goto dealloc;
-  }
-
-  memset(&packet, 0, sizeof(packet));
-  SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr));
-  packet.source_port = port;
-  packet.netif = recv_netif;
-  packet.pbuf = p;
-  packet.parse_offset = offset;
-  packet.tx_id = lwip_ntohs(hdr.id);
-  packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions);
-  packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr);
-
-#if LWIP_IPV6
-  if (IP_IS_V6(ip_current_dest_addr())) {
-    if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) {
-      packet.recv_unicast = 1;
-    }
-  }
-#endif
-#if LWIP_IPV4
-  if (!IP_IS_V6(ip_current_dest_addr())) {
-    if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) {
-      packet.recv_unicast = 1;
-    }
-  }
-#endif
-
-  if (hdr.flags1 & DNS_FLAG1_RESPONSE) {
-    mdns_handle_response(&packet);
-  } else {
-    mdns_handle_question(&packet);
-  }
-
-dealloc:
-  pbuf_free(p);
-}
-
-/**
- * @ingroup mdns
- * Initiate MDNS responder. Will open UDP sockets on port 5353
- */
-void
-mdns_resp_init(void)
-{
-  err_t res;
-
-  mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
-  LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL);
-#if LWIP_MULTICAST_TX_OPTIONS
-  udp_set_multicast_ttl(mdns_pcb, MDNS_TTL);
-#else
-  mdns_pcb->ttl = MDNS_TTL;
-#endif
-  res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT);
-  LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
-  udp_recv(mdns_pcb, mdns_recv, NULL);
-
-  mdns_netif_client_id = netif_alloc_client_data_id();
-}
-
-/**
- * @ingroup mdns
- * Announce IP settings have changed on netif.
- * Call this in your callback registered by netif_set_status_callback().
- * This function may go away in the future when netif supports registering
- * multiple callback functions.
- * @param netif The network interface where settings have changed.
- */
-void
-mdns_resp_netif_settings_changed(struct netif *netif)
-{
-  LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return);
-
-  if (NETIF_TO_HOST(netif) == NULL) {
-    return;
-  }
-
-  /* Announce on IPv6 and IPv4 */
-#if LWIP_IPV6
-   mdns_announce(netif, IP6_ADDR_ANY);
-#endif
-#if LWIP_IPV4
-   mdns_announce(netif, IP4_ADDR_ANY);
-#endif
-}
-
-/**
- * @ingroup mdns
- * Activate MDNS responder for a network interface and send announce packets.
- * @param netif The network interface to activate.
- * @param hostname Name to use. Queries for &lt;hostname&gt;.local will be answered
- *                 with the IP addresses of the netif. The hostname will be copied, the
- *                 given pointer can be on the stack.
- * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies
- * @return ERR_OK if netif was added, an err_t otherwise
- */
-err_t
-mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl)
-{
-  err_t res;
-  struct mdns_host* mdns;
-
-  LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL);
-  LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
-
-  LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL);
-  mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host));
-  LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM);
-
-  netif_set_client_data(netif, mdns_netif_client_id, mdns);
-
-  memset(mdns, 0, sizeof(struct mdns_host));
-  MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname)));
-  mdns->dns_ttl = dns_ttl;
-
-  /* Join multicast groups */
-#if LWIP_IPV4
-  res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group));
-  if (res != ERR_OK) {
-    goto cleanup;
-  }
-#endif
-#if LWIP_IPV6
-  res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group));
-  if (res != ERR_OK) {
-    goto cleanup;
-  }
-#endif
-
-  mdns_resp_netif_settings_changed(netif);
-  return ERR_OK;
-
-cleanup:
-  mem_free(mdns);
-  netif_set_client_data(netif, mdns_netif_client_id, NULL);
-  return res;
-}
-
-/**
- * @ingroup mdns
- * Stop responding to MDNS queries on this interface, leave multicast groups,
- * and free the helper structure and any of its services.
- * @param netif The network interface to remove.
- * @return ERR_OK if netif was removed, an err_t otherwise
- */
-err_t
-mdns_resp_remove_netif(struct netif *netif)
-{
-  int i;
-  struct mdns_host* mdns;
-
-  LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif);
-  mdns = NETIF_TO_HOST(netif);
-  LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL);
-
-  for (i = 0; i < MDNS_MAX_SERVICES; i++) {
-    struct mdns_service *service = mdns->services[i];
-    if (service) {
-      mem_free(service);
-    }
-  }
-
-  /* Leave multicast groups */
-#if LWIP_IPV4
-  igmp_leavegroup_netif(netif, ip_2_ip4(&v4group));
-#endif
-#if LWIP_IPV6
-  mld6_leavegroup_netif(netif, ip_2_ip6(&v6group));
-#endif
-
-  mem_free(mdns);
-  netif_set_client_data(netif, mdns_netif_client_id, NULL);
-  return ERR_OK;
-}
-
-/**
- * @ingroup mdns
- * Add a service to the selected network interface.
- * @param netif The network interface to publish this service on
- * @param name The name of the service
- * @param service The service type, like "_http"
- * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP
- *              for others ("_udp")
- * @param port The port the service listens to
- * @param dns_ttl Validity time in seconds to send out for service data in DNS replies
- * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to
- *               allow dynamic replies.
- * @param txt_data Userdata pointer for txt_fn
- * @return ERR_OK if the service was added to the netif, an err_t otherwise
- */
-err_t
-mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data)
-{
-  int i;
-  int slot = -1;
-  struct mdns_service *srv;
-  struct mdns_host* mdns;
-
-  LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif);
-  mdns = NETIF_TO_HOST(netif);
-  LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL);
-
-  LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
-  LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
-  LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL);
-
-  for (i = 0; i < MDNS_MAX_SERVICES; i++) {
-    if (mdns->services[i] == NULL) {
-      slot = i;
-      break;
-    }
-  }
-  LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM);
-
-  srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service));
-  LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM);
-
-  memset(srv, 0, sizeof(struct mdns_service));
-
-  MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name)));
-  MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service)));
-  srv->txt_fn = txt_fn;
-  srv->txt_userdata = txt_data;
-  srv->proto = (u16_t)proto;
-  srv->port = port;
-  srv->dns_ttl = dns_ttl;
-
-  mdns->services[slot] = srv;
-
-  /* Announce on IPv6 and IPv4 */
-#if LWIP_IPV6
-  mdns_announce(netif, IP6_ADDR_ANY);
-#endif
-#if LWIP_IPV4
-  mdns_announce(netif, IP4_ADDR_ANY);
-#endif
-
-  return ERR_OK;
-}
-
-/**
- * @ingroup mdns
- * Call this function from inside the service_get_txt_fn_t callback to add text data.
- * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte.
- * @param service The service provided to the get_txt callback
- * @param txt String to add to the TXT field.
- * @param txt_len Length of string
- * @return ERR_OK if the string was added to the reply, an err_t otherwise
- */
-err_t
-mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
-{
-  LWIP_ASSERT("mdns_resp_add_service: service != NULL", service);
-
-  /* Use a mdns_domain struct to store txt chunks since it is the same encoding */
-  return mdns_domain_add_label(&service->txtdata, txt, txt_len);
-}
-
-#endif /* LWIP_MDNS_RESPONDER */

+ 0 - 367
components/net/lwip-2.0.0/src/apps/netbiosns/netbiosns.c

@@ -1,367 +0,0 @@
-/**
- * @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 */

+ 0 - 749
components/net/lwip-2.0.0/src/apps/snmp/snmp_asn1.c

@@ -1,749 +0,0 @@
-/**
- * @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 */

+ 0 - 108
components/net/lwip-2.0.0/src/apps/snmp/snmp_asn1.h

@@ -1,108 +0,0 @@
-/**
- * @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 */

+ 0 - 1349
components/net/lwip-2.0.0/src/apps/snmp/snmp_core.c

@@ -1,1349 +0,0 @@
-/**
- * @file
- * MIB tree access/construction 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: Christiaan Simons <christiaan.simons@axon.tv>
- *         Martin Hentschel <info@cl-soft.de>
-*/
-
-/**
- * @defgroup snmp SNMPv2c agent
- * @ingroup apps
- * SNMPv2c compatible agent\n
- * There is also a MIB compiler and a MIB viewer in lwIP contrib repository
- * (lwip-contrib/apps/LwipMibCompiler).\n
- * The agent implements the most important MIB2 MIBs including IPv6 support
- * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version
- * whithout IPv6 statistics (TODO).\n
- * Rewritten by Martin Hentschel <info@cl-soft.de> and
- * Dirk Ziegelmeier <dziegel@gmx.de>\n
- * Work on SNMPv3 has started, but is not finished.\n
- *
- * 0 Agent Capabilities
- * ====================
- * 
- * Features:
- * ---------
- * - SNMPv2c support.
- * - Low RAM usage - no memory pools, stack only.
- * - MIB2 implementation is separated from SNMP stack.
- * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB.
- * - Simple and generic API for MIB implementation.
- * - Comfortable node types and helper functions for scalar arrays and tables.
- * - Counter64, bit and truthvalue datatype support.
- * - Callbacks for SNMP writes e.g. to implement persistency.
- * - Runs on two APIs: RAW and netconn.
- * - Async API is gone - the stack now supports netconn API instead,
- *   so blocking operations can be done in MIB calls.
- *   SNMP runs in a worker thread when netconn API is used.
- * - Simplified thread sync support for MIBs - useful when MIBs
- *   need to access variables shared with other threads where no locking is
- *   possible. Used in MIB2 to access lwIP stats from lwIP thread.
- * 
- * MIB compiler (code generator):
- * ------------------------------
- * - Provided in lwIP contrib repository.
- * - Written in C#. MIB viewer used Windows Forms.
- * - Developed on Windows with Visual Studio 2010.
- * - Can be compiled and used on all platforms with http://www.monodevelop.com/.
- * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4)
- *   (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate).
- * - MIB parser, C file generation framework and LWIP code generation are cleanly
- *   separated, which means the code may be useful as a base for code generation
- *   of other SNMP agents.
- * 
- * Notes:
- * ------
- * - Stack and MIB compiler were used to implement a Profinet device.
- *   Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB.
- * 
- * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416
- * -------------------------------------------
- *   Note the S in SNMP stands for "Simple". Note that "Simple" is
- *   relative. SNMP is simple compared to the complex ISO network
- *   management protocols CMIP (Common Management Information Protocol)
- *   and CMOT (CMip Over Tcp).
- * 
- * MIB II
- * ------
- *   The standard lwIP stack management information base.
- *   This is a required MIB, so this is always enabled.
- *   The groups EGP, CMOT and transmission are disabled by default.
- * 
- *   Most mib-2 objects are not writable except:
- *   sysName, sysLocation, sysContact, snmpEnableAuthenTraps.
- *   Writing to or changing the ARP and IP address and route
- *   tables is not possible.
- * 
- *   Note lwIP has a very limited notion of IP routing. It currently
- *   doen't have a route table and doesn't have a notion of the U,G,H flags.
- *   Instead lwIP uses the interface list with only one default interface
- *   acting as a single gateway interface (G) for the default route.
- * 
- *   The agent returns a "virtual table" with the default route 0.0.0.0
- *   for the default interface and network routes (no H) for each
- *   network interface in the netif_list.
- *   All routes are considered to be up (U).
- * 
- * Loading additional MIBs
- * -----------------------
- *   MIBs can only be added in compile-time, not in run-time.
- *  
- * 
- * 1 Building the Agent
- * ====================
- * First of all you'll need to add the following define
- * to your local lwipopts.h:
- * \#define LWIP_SNMP               1
- * 
- * and add the source files your makefile.
- * 
- * Note you'll might need to adapt you network driver to update
- * the mib2 variables for your interface.
- * 
- * 2 Running the Agent
- * ===================
- * The following function calls must be made in your program to
- * actually get the SNMP agent running.
- * 
- * Before starting the agent you should supply pointers
- * for sysContact, sysLocation, and snmpEnableAuthenTraps.
- * You can do this by calling
- * 
- * - snmp_mib2_set_syscontact()
- * - snmp_mib2_set_syslocation()
- * - snmp_set_auth_traps_enabled()
- * 
- * You can register a callback which is called on successful write access: 
- * snmp_set_write_callback().
- * 
- * Additionally you may want to set
- * 
- * - snmp_mib2_set_sysdescr()
- * - snmp_set_device_enterprise_oid()
- * - snmp_mib2_set_sysname()
- * 
- * Also before starting the agent you need to setup
- * one or more trap destinations using these calls:
- * 
- * - snmp_trap_dst_enable()
- * - snmp_trap_dst_ip_set()
- * 
- * If you need more than MIB2, set the MIBs you want to use
- * by snmp_set_mibs().
- * 
- * Finally, enable the agent by calling snmp_init()
- *
- * @defgroup snmp_core Core
- * @ingroup snmp
- * 
- * @defgroup snmp_traps Traps
- * @ingroup snmp
- */
-
-#include "lwip/apps/snmp_opts.h"
-
-#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/apps/snmp.h"
-#include "lwip/apps/snmp_core.h"
-#include "snmp_core_priv.h"
-#include "lwip/netif.h"
-#include <string.h>
-
-
-#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0))
-  #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP && LWIP_SNMP)
-  #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-
-struct snmp_statistics snmp_stats;
-static const struct snmp_obj_id  snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID};
-static const struct snmp_obj_id* snmp_device_enterprise_oid         = &snmp_device_enterprise_oid_default;
-
-const u32_t snmp_zero_dot_zero_values[] = { 0, 0 };
-const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values };
-
-
-#if SNMP_LWIP_MIB2
-#include "lwip/apps/snmp_mib2.h"
-static const struct snmp_mib* const default_mibs[] = { &mib2 };
-static u8_t snmp_num_mibs                          = 1;
-#else
-static const struct snmp_mib* const default_mibs[] = { NULL };
-static u8_t snmp_num_mibs                          = 0;
-#endif
-
-/* List of known mibs */
-static struct snmp_mib const * const *snmp_mibs = default_mibs;
-
-/**
- * @ingroup snmp_core
- * Sets the MIBs to use.
- * Example: call snmp_set_mibs() as follows:
- * static const struct snmp_mib *my_snmp_mibs[] = {
- *   &mib2,
- *   &private_mib
- * };
- * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs));
- */
-void
-snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs)
-{
-  LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL));
-  LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0));
-  snmp_mibs     = mibs;
-  snmp_num_mibs = num_mibs;
-}
-
-/**
- * @ingroup snmp_core
- * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device)
- * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used).
- * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor
- * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It
- * is not allowed to use LWIP enterprise ID!
- * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own 
- * enterprise oid.
- * e.g.
- * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a)
- * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b)
- * for more details see description of 'sysObjectID' field in RFC1213-MIB
- */
-void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid)
-{
-  if (device_enterprise_oid == NULL) {
-    snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default;
-  } else {
-    snmp_device_enterprise_oid = device_enterprise_oid;
-  }
-}
-
-/**
- * @ingroup snmp_core
- * Get 'device enterprise oid' 
- */
-const struct snmp_obj_id* snmp_get_device_enterprise_oid(void)
-{
-  return snmp_device_enterprise_oid;
-}
-
-#if LWIP_IPV4
-/**
- * Conversion from InetAddressIPv4 oid to lwIP ip4_addr
- * @param oid points to u32_t ident[4] input
- * @param ip points to output struct
- */
-u8_t
-snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip)
-{
-  if ((oid[0] > 0xFF) ||
-      (oid[1] > 0xFF) ||
-      (oid[2] > 0xFF) ||
-      (oid[3] > 0xFF)) {
-    ip4_addr_copy(*ip, *IP4_ADDR_ANY4);
-    return 0;
-  }
-
-  IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]);
-  return 1;
-}
-
-/**
- * Convert ip4_addr to InetAddressIPv4 (no InetAddressType)
- * @param ip points to input struct
- * @param oid points to u32_t ident[4] output
- */
-void
-snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid)
-{
-  oid[0] = ip4_addr1(ip);
-  oid[1] = ip4_addr2(ip);
-  oid[2] = ip4_addr3(ip);
-  oid[3] = ip4_addr4(ip);
-}
-#endif /* LWIP_IPV4 */
-
-#if LWIP_IPV6
-/**
- * Conversion from InetAddressIPv6 oid to lwIP ip6_addr
- * @param oid points to u32_t oid[16] input
- * @param ip points to output struct
- */
-u8_t
-snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip)
-{
-  if ((oid[0]  > 0xFF) ||
-      (oid[1]  > 0xFF) ||
-      (oid[2]  > 0xFF) ||
-      (oid[3]  > 0xFF) ||
-      (oid[4]  > 0xFF) ||
-      (oid[5]  > 0xFF) ||
-      (oid[6]  > 0xFF) ||
-      (oid[7]  > 0xFF) ||
-      (oid[8]  > 0xFF) ||
-      (oid[9]  > 0xFF) ||
-      (oid[10] > 0xFF) ||
-      (oid[11] > 0xFF) ||
-      (oid[12] > 0xFF) ||
-      (oid[13] > 0xFF) ||
-      (oid[14] > 0xFF) ||
-      (oid[15] > 0xFF)) {
-    ip6_addr_set_any(ip);
-    return 0;
-  }
-
-  ip->addr[0] = (oid[0]  << 24) | (oid[1]  << 16) | (oid[2]  << 8) | (oid[3]  << 0);
-  ip->addr[1] = (oid[4]  << 24) | (oid[5]  << 16) | (oid[6]  << 8) | (oid[7]  << 0);
-  ip->addr[2] = (oid[8]  << 24) | (oid[9]  << 16) | (oid[10] << 8) | (oid[11] << 0);
-  ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0);
-  return 1;
-}
-
-/**
- * Convert ip6_addr to InetAddressIPv6 (no InetAddressType)
- * @param ip points to input struct
- * @param oid points to u32_t ident[16] output
- */
-void
-snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid)
-{
-  oid[0]  = (ip->addr[0] & 0xFF000000) >> 24;
-  oid[1]  = (ip->addr[0] & 0x00FF0000) >> 16;
-  oid[2]  = (ip->addr[0] & 0x0000FF00) >>  8;
-  oid[3]  = (ip->addr[0] & 0x000000FF) >>  0;
-  oid[4]  = (ip->addr[1] & 0xFF000000) >> 24;
-  oid[5]  = (ip->addr[1] & 0x00FF0000) >> 16;
-  oid[6]  = (ip->addr[1] & 0x0000FF00) >>  8;
-  oid[7]  = (ip->addr[1] & 0x000000FF) >>  0;
-  oid[8]  = (ip->addr[2] & 0xFF000000) >> 24;
-  oid[9]  = (ip->addr[2] & 0x00FF0000) >> 16;
-  oid[10] = (ip->addr[2] & 0x0000FF00) >>  8;
-  oid[11] = (ip->addr[2] & 0x000000FF) >>  0;
-  oid[12] = (ip->addr[3] & 0xFF000000) >> 24;
-  oid[13] = (ip->addr[3] & 0x00FF0000) >> 16;
-  oid[14] = (ip->addr[3] & 0x0000FF00) >>  8;
-  oid[15] = (ip->addr[3] & 0x000000FF) >>  0;
-}
-#endif /* LWIP_IPV6 */
-
-#if LWIP_IPV4 || LWIP_IPV6
-/**
- * Convert to InetAddressType+InetAddress+InetPortNumber
- * @param ip IP address
- * @param port Port
- * @param oid OID
- * @return OID length
- */
-u8_t
-snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid)
-{
-  u8_t idx;
-
-  idx = snmp_ip_to_oid(ip, oid);
-  oid[idx] = port;
-  idx++;
-
-  return idx;
-}
-
-/**
- * Convert to InetAddressType+InetAddress
- * @param ip IP address
- * @param oid OID
- * @return OID length
- */
-u8_t
-snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid)
-{
-  if (IP_IS_ANY_TYPE_VAL(*ip)) {
-    oid[0] = 0; /* any */
-    oid[1] = 0; /* no IP OIDs follow */
-    return 2;
-  } else if (IP_IS_V6(ip)) {
-#if LWIP_IPV6
-    oid[0] = 2; /* ipv6 */
-    oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */
-    snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]);
-    return 18;
-#else /* LWIP_IPV6 */
-    return 0;
-#endif /* LWIP_IPV6 */
-  } else {
-#if LWIP_IPV4
-    oid[0] = 1; /* ipv4 */
-    oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */
-    snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]);
-    return 6;
-#else /* LWIP_IPV4 */
-    return 0;
-#endif /* LWIP_IPV4 */
-  }
-}
-
-/**
- * Convert from InetAddressType+InetAddress to ip_addr_t
- * @param oid OID
- * @param oid_len OID length
- * @param ip IP address
- * @return Parsed OID length
- */
-u8_t
-snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip)
-{
-  /* InetAddressType */
-  if (oid_len < 1) {
-    return 0;
-  }
-
-  if (oid[0] == 0) { /* any */
-    /* 1x InetAddressType, 1x OID len */
-    if (oid_len < 2) {
-      return 0;
-    }
-    if (oid[1] != 0) {
-      return 0;
-    }
-
-    memset(ip, 0, sizeof(*ip));
-    IP_SET_TYPE(ip, IPADDR_TYPE_ANY);
-
-    return 2;
-  } else if (oid[0] == 1) { /* ipv4 */
-#if LWIP_IPV4
-    /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */
-    if (oid_len < 6) {
-      return 0;
-    }
-
-    /* 4x ipv4 OID */
-    if (oid[1] != 4) {
-      return 0;
-    }
-
-    IP_SET_TYPE(ip, IPADDR_TYPE_V4);
-    if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) {
-      return 0;
-    }
-
-    return 6;
-#else /* LWIP_IPV4 */
-    return 0;
-#endif /* LWIP_IPV4 */
-  } else if (oid[0] == 2) { /* ipv6 */
-#if LWIP_IPV6
-    /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */
-    if (oid_len < 18) {
-      return 0;
-    }
-
-    /* 16x ipv6 OID */
-    if (oid[1] != 16) {
-      return 0;
-    }
-
-    IP_SET_TYPE(ip, IPADDR_TYPE_V6);
-    if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) {
-      return 0;
-    }
-
-    return 18;
-#else /* LWIP_IPV6 */
-    return 0;
-#endif /* LWIP_IPV6 */
-  } else { /* unsupported InetAddressType */
-    return 0;
-  }
-}
-
-/**
- * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t
- * @param oid OID
- * @param oid_len OID length
- * @param ip IP address
- * @param port Port
- * @return Parsed OID length
- */
-u8_t
-snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port)
-{
-  u8_t idx = 0;
-
-  /* InetAddressType + InetAddress */
-  idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip);
-  if (idx == 0) {
-    return 0;
-  }
-
-  /* InetPortNumber */
-  if (oid_len < (idx+1)) {
-    return 0;
-  }
-  if (oid[idx] > 0xffff) {
-    return 0;
-  }
-  *port = (u16_t)oid[idx];
-  idx++;
-
-  return idx;
-}
-
-#endif /* LWIP_IPV4 || LWIP_IPV6 */
-
-/**
- * Assign an OID to struct snmp_obj_id
- * @param target Assignment target 
- * @param oid OID
- * @param oid_len OID length
- */
-void
-snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
-{
-  LWIP_ASSERT("oid_len <= LWIP_SNMP_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN);
-
-  target->len = oid_len;
-
-  if (oid_len > 0) {
-    MEMCPY(target->id, oid, oid_len * sizeof(u32_t));
-  }
-}
-
-/**
- * Prefix an OID to OID in struct snmp_obj_id
- * @param target Assignment target to prefix
- * @param oid OID
- * @param oid_len OID length
- */
-void
-snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
-{
-  LWIP_ASSERT("target->len + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN);
-
-  if (oid_len > 0) {
-    /* move existing OID to make room at the beginning for OID to insert */
-    int i;
-    for (i = target->len-1; i>=0; i--) {
-      target->id[i + oid_len] = target->id[i];
-    }
-
-    /* paste oid at the beginning */
-    MEMCPY(target->id, oid, oid_len * sizeof(u32_t));
-  }
-}
-
-/**
- * Combine two OIDs into struct snmp_obj_id
- * @param target Assignmet target
- * @param oid1 OID 1
- * @param oid1_len OID 1 length
- * @param oid2 OID 2
- * @param oid2_len OID 2 length
- */
-void
-snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
-{
-  snmp_oid_assign(target, oid1, oid1_len);
-  snmp_oid_append(target, oid2, oid2_len);
-}
-
-/**
- * Append OIDs to struct snmp_obj_id
- * @param target Assignment target to append to
- * @param oid OID
- * @param oid_len OID length
- */
-void
-snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len)
-{
-  LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN);
-
-  if (oid_len > 0) {
-    MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t));
-    target->len += oid_len;
-  }
-}
-
-/**
- * Compare two OIDs
- * @param oid1 OID 1
- * @param oid1_len OID 1 length
- * @param oid2 OID 2
- * @param oid2_len OID 2 length
- * @return -1: OID1&lt;OID2  1: OID1 &gt;OID2 0: equal
- */
-s8_t
-snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
-{
-  u8_t level = 0;
-  LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0));
-  LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0));
-
-  while ((level < oid1_len) && (level < oid2_len)) {
-    if (*oid1 < *oid2) {
-      return -1;
-    }
-    if (*oid1 > *oid2) {
-      return 1;
-    }
-
-    level++;
-    oid1++;
-    oid2++;
-  }
-
-  /* common part of both OID's is equal, compare length */
-  if (oid1_len < oid2_len) {
-    return -1;
-  }
-  if (oid1_len > oid2_len) {
-    return 1;
-  }
-
-  /* they are equal */
-  return 0;
-}
-
-
-/**
- * Check of two OIDs are equal
- * @param oid1 OID 1
- * @param oid1_len OID 1 length
- * @param oid2 OID 2
- * @param oid2_len OID 2 length
- * @return 1: equal 0: non-equal
- */
-u8_t
-snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
-{
-  return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0;
-}
-
-/**
- * Convert netif to interface index
- * @param netif netif
- * @return index
- */
-u8_t
-netif_to_num(const struct netif *netif)
-{
-  u8_t result = 0;
-  struct netif *netif_iterator = netif_list;
-
-  while (netif_iterator != NULL) {
-    result++;
-
-    if (netif_iterator == netif) {
-      return result;
-    }
-
-    netif_iterator = netif_iterator->next;
-  }
-
-  LWIP_ASSERT("netif not found in netif_list", 0);
-  return 0;
-}
-
-static const struct snmp_mib*
-snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len)
-{
-  const u32_t* list_oid;
-  const u32_t* searched_oid;
-  u8_t i, l;
-
-  u8_t max_match_len = 0;
-  const struct snmp_mib* matched_mib = NULL;
-
-  LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL));
-
-  if (oid_len == 0) {
-    return NULL;
-  }
-
-  for (i = 0; i < snmp_num_mibs; i++) {
-    LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL));
-    LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL));
-
-    if (oid_len >= snmp_mibs[i]->base_oid_len) {
-      l            = snmp_mibs[i]->base_oid_len;
-      list_oid     = snmp_mibs[i]->base_oid;
-      searched_oid = oid;
-
-      while (l > 0) {
-        if (*list_oid != *searched_oid) {
-          break;
-        }
-
-        l--;
-        list_oid++;
-        searched_oid++;
-      }
-
-      if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) {
-        max_match_len = snmp_mibs[i]->base_oid_len;
-        matched_mib = snmp_mibs[i];
-      }
-    }
-  }
-
-  return matched_mib;
-}
-
-static const struct snmp_mib*
-snmp_get_next_mib(const u32_t *oid, u8_t oid_len)
-{
-  u8_t i;
-  const struct snmp_mib* next_mib = NULL;
-
-  LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL));
-
-  if (oid_len == 0) {
-    return NULL;
-  }
-
-  for (i = 0; i < snmp_num_mibs; i++) {
-    if (snmp_mibs[i]->base_oid != NULL) {
-      /* check if mib is located behind starting point */
-      if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) {
-        if ((next_mib == NULL) ||
-            (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len,
-                              next_mib->base_oid, next_mib->base_oid_len) < 0)) {
-          next_mib = snmp_mibs[i];
-        }
-      }
-    }
-  }
-
-  return next_mib;
-}
-
-static const struct snmp_mib*
-snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len)
-{
-  const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len);
-
-  LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL));
-  LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0));
-
-  if (next_mib != NULL) {
-    if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) {
-      return next_mib;
-    }
-  }
-
-  return NULL;
-}
-
-u8_t
-snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance)
-{
-  u8_t result = SNMP_ERR_NOSUCHOBJECT;
-  const struct snmp_mib *mib;
-  const struct snmp_node *mn = NULL;
-
-  mib = snmp_get_mib_from_oid(oid, oid_len);
-  if (mib != NULL) {
-    u8_t oid_instance_len;
-
-    mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len);
-    if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) {
-      /* get instance */
-      const struct snmp_leaf_node* leaf_node = (const struct snmp_leaf_node*)(const void*)mn;
-
-      node_instance->node = mn;
-      snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len);
-
-      result = leaf_node->get_instance(
-        oid,
-        oid_len - oid_instance_len,
-        node_instance);
-
-#ifdef LWIP_DEBUG
-      if (result == SNMP_ERR_NOERROR) {
-        if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) {
-          LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n"));
-        }
-        if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) {
-          LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n"));
-        }
-      }
-#endif
-    }
-  }
-
-  return result;
-}
-
-u8_t
-snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance)
-{
-  const struct snmp_mib      *mib;
-  const struct snmp_node *mn = NULL;
-  const u32_t* start_oid     = NULL;
-  u8_t         start_oid_len = 0;
-
-  /* resolve target MIB from passed OID */
-  mib = snmp_get_mib_from_oid(oid, oid_len);
-  if (mib == NULL) {
-    /* passed OID does not reference any known MIB, start at the next closest MIB */
-    mib = snmp_get_next_mib(oid, oid_len);
-
-    if (mib != NULL) {
-      start_oid     = mib->base_oid;
-      start_oid_len = mib->base_oid_len;
-    }
-  } else {
-    start_oid     = oid;
-    start_oid_len = oid_len;
-  }
-
-  /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */
-  while ((mib != NULL) && (mn == NULL)) {
-    u8_t oid_instance_len;
-
-    /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */
-    mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len);
-    if (mn != NULL) {
-      snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */
-      snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */
-    } else {
-      /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */
-      mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid);
-      node_instance->instance_oid.len = 0;
-    }
-
-    /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */
-    node_instance->node = mn;
-    while (mn != NULL) {
-       u8_t result;
-
-      /* clear fields which may have values from previous loops */
-      node_instance->asn1_type        = 0;
-      node_instance->access           = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE;
-      node_instance->get_value        = NULL;
-      node_instance->set_test         = NULL;
-      node_instance->set_value        = NULL;
-      node_instance->release_instance = NULL;
-      node_instance->reference.ptr    = NULL;
-      node_instance->reference_len    = 0;
-
-      result = ((const struct snmp_leaf_node*)(const void*)mn)->get_next_instance(
-        node_oid->id,
-        node_oid->len,
-        node_instance);
-
-      if (result == SNMP_ERR_NOERROR) {
-#ifdef LWIP_DEBUG
-        if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) {
-          LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n"));
-        }
-        if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) {
-          LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n"));
-        }
-#endif
-
-        /* validate node because the node may be not accessible for example (but let the caller decide what is valid */
-        if ((validate_node_instance_method == NULL) ||
-            (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) {
-          /* node_oid "returns" the full result OID (including the instance part) */
-          snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len);
-          break;
-        }
-
-        if (node_instance->release_instance != NULL) {
-          node_instance->release_instance(node_instance);
-        }
-        /*
-        the instance itself is not valid, ask for next instance from same node.
-        we don't have to change any variables because node_instance->instance_oid is used as input (starting point)
-        as well as output (resulting next OID), so we have to simply call get_next_instance method again
-        */
-      } else {
-        if (node_instance->release_instance != NULL) {
-          node_instance->release_instance(node_instance);
-        }
-
-        /* the node has no further instance, skip to next node */
-        mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */
-        if (mn != NULL) {
-          /* prepare for next loop */
-          snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len);
-          node_instance->instance_oid.len = 0;
-          node_instance->node = mn;
-        }
-      }
-    }
-
-    if (mn != NULL) {
-      /*
-      we found a suitable next node,
-      now we have to check if a inner MIB is located between the searched OID and the resulting OID.
-      this is possible because MIB's may be located anywhere in the global tree, that means also in 
-      the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another
-      MIB having .3 as root node may exist)
-      */
-      const struct snmp_mib *intermediate_mib;
-      intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len);
-
-      if (intermediate_mib != NULL) {
-        /* search for first node inside intermediate mib in next loop */
-        if (node_instance->release_instance != NULL) {
-          node_instance->release_instance(node_instance);
-        }
-
-        mn            = NULL;
-        mib           = intermediate_mib;
-        start_oid     = mib->base_oid;
-        start_oid_len = mib->base_oid_len;
-      }
-      /* else { we found out target node } */
-    } else {
-      /*
-      there is no further (suitable) node inside this MIB, search for the next MIB with following priority
-      1. search for inner MIB's (whose root is located inside tree of current MIB)
-      2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any
-      3. take the next closest MIB (not being related to the current MIB)
-      */
-      const struct snmp_mib *next_mib;
-      next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */
-
-      /* is the found MIB an inner MIB? (point 1) */
-      if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) &&
-          (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) {
-        /* yes it is -> continue at inner MIB */
-        mib = next_mib;
-        start_oid     = mib->base_oid;
-        start_oid_len = mib->base_oid_len;
-      } else {
-        /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */
-        if (mib->base_oid_len > 1) {
-          mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1);
-
-          if (mib == NULL) {
-            /* no surrounding mib, use next mib encountered above (point 3) */
-            mib = next_mib;
-
-            if (mib != NULL) {
-              start_oid     = mib->base_oid;
-              start_oid_len = mib->base_oid_len;
-            }
-          }
-          /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */
-        }
-      }
-    }
-  }
-
-  if (mib == NULL) {
-    /* loop is only left when mib == null (error) or mib_node != NULL (success) */
-    return SNMP_ERR_ENDOFMIBVIEW;
-  }
-
-  return SNMP_ERR_NOERROR;
-}
-
-/**
- * Searches tree for the supplied object identifier.
- *
- */
-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* const* node = &mib->root_node;
-  u8_t oid_offset = mib->base_oid_len;
-
-  while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) {
-    /* search for matching sub node */
-    u32_t subnode_oid = *(oid + oid_offset);
-
-    u32_t i = (*(const struct snmp_tree_node* const*)node)->subnode_count;
-    node    = (*(const struct snmp_tree_node* const*)node)->subnodes;
-    while ((i > 0) && ((*node)->oid != subnode_oid)) {
-      node++;
-      i--;
-    }
-
-    if (i == 0) {
-      /* no matching subnode found */
-      return NULL;
-    }
-
-    oid_offset++;
-  }
-
-  if ((*node)->node_type != SNMP_NODE_TREE) {
-    /* we found a leaf node */
-    *oid_instance_len = oid_len - oid_offset;
-    return (*node);
-  }
-
-  return NULL;
-}
-
-const struct snmp_node*
-snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret)
-{
-  u8_t  oid_offset = mib->base_oid_len;
-  const struct snmp_node* const* node;
-  const struct snmp_tree_node* node_stack[SNMP_MAX_OBJ_ID_LEN];
-  s32_t nsi = 0; /* NodeStackIndex */
-  u32_t subnode_oid;
-
-  if (mib->root_node->node_type != SNMP_NODE_TREE) {
-    /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */
-    return NULL;
-  }
-
-  /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */
-  node_stack[nsi] = (const struct snmp_tree_node*)(const void*)mib->root_node;
-  while (oid_offset < oid_len) {
-    /* search for matching sub node */
-    u32_t i = node_stack[nsi]->subnode_count;
-    node    = node_stack[nsi]->subnodes;
-
-    subnode_oid = *(oid + oid_offset);
-
-    while ((i > 0) && ((*node)->oid != subnode_oid)) {
-      node++;
-      i--;
-    }
-
-    if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) {
-      /* no (matching) tree-subnode found */
-      break;
-    }
-    nsi++;
-    node_stack[nsi] = (const struct snmp_tree_node*)(const void*)(*node);
-
-    oid_offset++;
-  }
-
-
-  if (oid_offset >= oid_len) {
-    /* passed oid references a tree node -> return first useable sub node of it */
-    subnode_oid = 0;
-  } else {
-    subnode_oid = *(oid + oid_offset) + 1;
-  }
-
-  while (nsi >= 0) {
-    const struct snmp_node* subnode = NULL;
-
-    /* find next node on current level */
-    s32_t i        = node_stack[nsi]->subnode_count;
-    node           = node_stack[nsi]->subnodes;
-    while (i > 0) {
-      if ((*node)->oid == subnode_oid) {
-        subnode = *node;
-        break;
-      } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) {
-        subnode = *node;
-      }
-
-      node++;
-      i--;
-    }
-
-    if (subnode == NULL) {
-      /* no further node found on this level, go one level up and start searching with index of current node*/
-      subnode_oid = node_stack[nsi]->node.oid + 1;
-      nsi--;
-    } else {
-      if (subnode->node_type == SNMP_NODE_TREE) {
-        /* next is a tree node, go into it and start searching */
-        nsi++;
-        node_stack[nsi] = (const struct snmp_tree_node*)(const void*)subnode;
-        subnode_oid = 0;
-      } else {
-        /* we found a leaf node -> fill oidret and return it */
-        snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len);
-        i = 1;
-        while (i <= nsi) {
-          oidret->id[oidret->len] = node_stack[i]->node.oid;
-          oidret->len++;
-          i++;
-        }
-
-        oidret->id[oidret->len] = subnode->oid;
-        oidret->len++;
-
-        return subnode;
-      }
-    }
-  }
-
-  return NULL;
-}
-
-/** initialize struct next_oid_state using this function before passing it to next_oid_check */
-void
-snmp_next_oid_init(struct snmp_next_oid_state *state,
-  const u32_t *start_oid, u8_t start_oid_len,
-  u32_t *next_oid_buf, u8_t next_oid_max_len)
-{
-  state->start_oid        = start_oid;
-  state->start_oid_len    = start_oid_len;
-  state->next_oid         = next_oid_buf;
-  state->next_oid_len     = 0;
-  state->next_oid_max_len = next_oid_max_len;
-  state->status           = SNMP_NEXT_OID_STATUS_NO_MATCH;
-}
-
-/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check();
-this methid is intended if the complete OID is not yet known but it is very expensive to build it up,
-so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/
-u8_t
-snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len)
-{
-  if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) {
-    u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len;
-
-    /* check passed OID is located behind start offset */
-    if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) {
-      /* check if new oid is located closer to start oid than current closest oid */
-      if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) ||
-        (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) {
-        return 1;
-      }
-    }
-  }
-
-  return 0;
-}
-
-/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */
-u8_t
-snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference)
-{
-  /* do not overwrite a fail result */
-  if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) {
-    /* check passed OID is located behind start offset */
-    if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) {
-      /* check if new oid is located closer to start oid than current closest oid */
-      if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) ||
-        (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) {
-        if (oid_len <= state->next_oid_max_len) {
-          MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t));
-          state->next_oid_len = oid_len;
-          state->status       = SNMP_NEXT_OID_STATUS_SUCCESS;
-          state->reference    = reference;
-          return 1;
-        } else {
-          state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL;
-        }
-      }
-    }
-  }
-
-  return 0;
-}
-
-u8_t
-snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len)
-{
-  u8_t i;
-
-  if (oid_len != oid_ranges_len) {
-    return 0;
-  }
-
-  for (i = 0; i < oid_ranges_len; i++) {
-    if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) {
-      return 0;
-    }
-  }
-
-  return 1;
-}
-
-snmp_err_t
-snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value)
-{
-  LWIP_UNUSED_ARG(instance);
-  LWIP_UNUSED_ARG(value_len);
-  LWIP_UNUSED_ARG(value);
-
-  return SNMP_ERR_NOERROR;
-}
-
-/**
- * Decodes BITS pseudotype value from ASN.1 OctetString.
- *
- * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly
- * be encoded/decoded by the agent. Instead call this function as required from
- * get/test/set methods.
- *
- * @param buf points to a buffer holding the ASN1 octet string
- * @param buf_len length of octet string
- * @param bit_value decoded Bit value with Bit0 == LSB
- * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit
- */
-err_t
-snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value)
-{
-  u8_t b;
-  u8_t bits_processed = 0;
-  *bit_value = 0;
-
-  while (buf_len > 0) {
-    /* any bit set in this byte? */
-    if (*buf != 0x00) {
-      if (bits_processed >= 32) {
-        /* accept more than 4 bytes, but only when no bits are set */
-        return ERR_VAL;
-      }
-
-      b = *buf;
-      do {
-        if (b & 0x80) {
-          *bit_value |= (1 << bits_processed);
-        }
-        bits_processed++;
-        b <<= 1;
-      }
-      while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */
-    } else {
-      bits_processed += 8;
-    }
-
-    buf_len--;
-    buf++;
-  }
-
-  return ERR_OK;
-}
-
-err_t
-snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value)
-{
-  /* defined by RFC1443:
-   TruthValue ::= TEXTUAL-CONVENTION
-    STATUS       current
-    DESCRIPTION
-     "Represents a boolean value."
-    SYNTAX       INTEGER { true(1), false(2) }
-  */
-
-  if ((asn1_value == NULL) || (bool_value == NULL)) {
-    return ERR_ARG;
-  }
-
-  if (*asn1_value == 1) {
-    *bool_value = 1;
-  } else if (*asn1_value == 2) {
-    *bool_value = 0;
-  } else {
-    return ERR_VAL;
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Encodes BITS pseudotype value into ASN.1 OctetString.
- *
- * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly
- * be encoded/decoded by the agent. Instead call this function as required from
- * get/test/set methods.
- *
- * @param buf points to a buffer where the resulting ASN1 octet string is stored to
- * @param buf_len max length of the bufffer
- * @param bit_value Bit value to encode with Bit0 == LSB
- * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value)
- * @return number of bytes used from buffer to store the resulting OctetString
- */
-u8_t
-snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count)
-{
-  u8_t len = 0;
-  u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */
-
-  while ((buf_len > 0) && (bit_value != 0x00)) {
-    s8_t i = 7;
-    *buf = 0x00;
-    while (i >= 0) {
-      if (bit_value & 0x01) {
-        *buf |= 0x01;
-      }
-
-      if (i > 0) {
-        *buf <<= 1;
-      }
-
-      bit_value >>= 1;
-      i--;
-    }
-
-    buf++;
-    buf_len--;
-    len++;
-  }
-
-  if (len < min_bytes) {
-    buf     += len;
-    buf_len -= len;
-
-    while ((len < min_bytes) && (buf_len > 0)) {
-      *buf = 0x00;
-      buf++;
-      buf_len--;
-      len++;
-    }
-  }
-
-  return len;
-}
-
-u8_t
-snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value)
-{
-  /* defined by RFC1443:
-   TruthValue ::= TEXTUAL-CONVENTION
-    STATUS       current
-    DESCRIPTION
-     "Represents a boolean value."
-    SYNTAX       INTEGER { true(1), false(2) }
-  */
-
-  if (asn1_value == NULL) {
-    return 0;
-  }
-
-  if (bool_value) {
-    *asn1_value = 1; /* defined by RFC1443 */
-  } else {
-    *asn1_value = 2; /* defined by RFC1443 */
-  }
-
-  return sizeof(s32_t);
-}
-
-#endif /* LWIP_SNMP */

+ 0 - 76
components/net/lwip-2.0.0/src/apps/snmp/snmp_core_priv.h

@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: 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 */

+ 0 - 116
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2.c

@@ -1,116 +0,0 @@
-/**
- * @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 */

+ 0 - 182
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_icmp.c

@@ -1,182 +0,0 @@
-/**
- * @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 */

+ 0 - 375
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_interfaces.c

@@ -1,375 +0,0 @@
-/**
- * @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 */

+ 0 - 743
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_ip.c

@@ -1,743 +0,0 @@
-/**
- * @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, &ethaddr);
-
-  /* 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, &ethaddr)) {
-      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, &ethaddr)) {
-      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), (void*)(size_t)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((u8_t)(size_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 */

+ 0 - 227
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_snmp.c

@@ -1,227 +0,0 @@
-/**
- * @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 */

+ 0 - 377
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_system.c

@@ -1,377 +0,0 @@
-/**
- * @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 */

+ 0 - 594
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_tcp.c

@@ -1,594 +0,0 @@
-/**
- * @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 */

+ 0 - 357
components/net/lwip-2.0.0/src/apps/snmp/snmp_mib2_udp.c

@@ -1,357 +0,0 @@
-/**
- * @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 */

+ 0 - 1668
components/net/lwip-2.0.0/src/apps/snmp/snmp_msg.c

@@ -1,1668 +0,0 @@
-/**
- * @file
- * SNMP message processing (RFC1157).
- */
-
-/*
- * 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>
- */
-
-#include "lwip/apps/snmp_opts.h"
-
-#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
-
-#include "snmp_msg.h"
-#include "snmp_asn1.h"
-#include "snmp_core_priv.h"
-#include "lwip/ip_addr.h"
-#include "lwip/stats.h"
-
-#if LWIP_SNMP_V3
-#include "lwip/apps/snmpv3.h"
-#include "snmpv3_priv.h"
-#ifdef LWIP_SNMPV3_INCLUDE_ENGINE
-#include LWIP_SNMPV3_INCLUDE_ENGINE
-#endif
-#endif
-
-#include <string.h>
-
-/* public (non-static) constants */
-/** SNMP community string */
-const char *snmp_community = SNMP_COMMUNITY;
-/** SNMP community string for write access */
-const char *snmp_community_write = SNMP_COMMUNITY_WRITE;
-/** SNMP community string for sending traps */
-const char *snmp_community_trap = SNMP_COMMUNITY_TRAP;
-
-snmp_write_callback_fct snmp_write_callback     = NULL;
-void*                   snmp_write_callback_arg = NULL;
-
-/**
- * @ingroup snmp_core
- * Returns current SNMP community string.
- * @return current SNMP community string
- */
-const char *
-snmp_get_community(void)
-{
-  return snmp_community;
-}
-
-/**
- * @ingroup snmp_core
- * Sets SNMP community string.
- * The string itself (its storage) must be valid throughout the whole life of
- * program (or until it is changed to sth else).
- *
- * @param community is a pointer to new community string
- */
-void
-snmp_set_community(const char * const community)
-{
-  LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
-  snmp_community = community;
-}
-
-/**
- * @ingroup snmp_core
- * Returns current SNMP write-access community string.
- * @return current SNMP write-access community string
- */
-const char *
-snmp_get_community_write(void)
-{
-  return snmp_community_write;
-}
-
-/**
- * @ingroup snmp_traps
- * Returns current SNMP community string used for sending traps.
- * @return current SNMP community string used for sending traps
- */
-const char *
-snmp_get_community_trap(void)
-{
-  return snmp_community_trap;
-}
-
-/**
- * @ingroup snmp_core
- * Sets SNMP community string for write-access.
- * The string itself (its storage) must be valid throughout the whole life of
- * program (or until it is changed to sth else).
- *
- * @param community is a pointer to new write-access community string
- */
-void
-snmp_set_community_write(const char * const community)
-{
-  LWIP_ASSERT("community string must not be NULL", community != NULL);
-  LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
-  snmp_community_write = community;
-}
-
-/**
- * @ingroup snmp_traps
- * Sets SNMP community string used for sending traps.
- * The string itself (its storage) must be valid throughout the whole life of
- * program (or until it is changed to sth else).
- *
- * @param community is a pointer to new trap community string
- */
-void
-snmp_set_community_trap(const char * const community)
-{
-  LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
-  snmp_community_trap = community;
-}
-
-/**
- * @ingroup snmp_core
- * Callback fired on every successful write access
- */
-void 
-snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg)
-{
-  snmp_write_callback     = write_callback;
-  snmp_write_callback_arg = callback_arg;
-}
-
-/* ----------------------------------------------------------------------- */
-/* forward declarations */
-/* ----------------------------------------------------------------------- */
-
-static err_t snmp_process_get_request(struct snmp_request *request);
-static err_t snmp_process_getnext_request(struct snmp_request *request);
-static err_t snmp_process_getbulk_request(struct snmp_request *request);
-static err_t snmp_process_set_request(struct snmp_request *request);
-
-static err_t snmp_parse_inbound_frame(struct snmp_request *request);
-static err_t snmp_prepare_outbound_frame(struct snmp_request *request);
-static err_t snmp_complete_outbound_frame(struct snmp_request *request);
-static void snmp_execute_write_callbacks(struct snmp_request *request);
-
-
-/* ----------------------------------------------------------------------- */
-/* implementation */
-/* ----------------------------------------------------------------------- */
-
-void
-snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port)
-{
-  err_t err;
-  struct snmp_request request;
-   
-  memset(&request, 0, sizeof(request));
-  request.handle       = handle;
-  request.source_ip    = source_ip;
-  request.source_port  = port;
-  request.inbound_pbuf = p;
-
-  snmp_stats.inpkts++;
-
-  err = snmp_parse_inbound_frame(&request);
-  if (err == ERR_OK) {
-    err = snmp_prepare_outbound_frame(&request);
-    if (err == ERR_OK) {
-
-      if (request.error_status == SNMP_ERR_NOERROR) {
-        /* only process frame if we do not already have an error to return (e.g. all readonly) */
-        if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) {
-          err = snmp_process_get_request(&request);
-        } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) {
-          err = snmp_process_getnext_request(&request);
-        } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
-          err = snmp_process_getbulk_request(&request);
-        } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
-          err = snmp_process_set_request(&request);
-        }
-      }
-
-      if (err == ERR_OK) {
-        err = snmp_complete_outbound_frame(&request);
-      
-        if (err == ERR_OK) {
-          err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port);
-
-          if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) 
-            && (request.error_status == SNMP_ERR_NOERROR) 
-            && (snmp_write_callback != NULL)) {
-            /* raise write notification for all written objects */
-            snmp_execute_write_callbacks(&request);
-          }
-        }
-      }
-    }
-  
-    if (request.outbound_pbuf != NULL) {
-      pbuf_free(request.outbound_pbuf);
-    }
-  }
-}
-
-static u8_t
-snmp_msg_getnext_validate_node_inst(struct snmp_node_instance* node_instance, void* validate_arg)
-{
-  if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) {
-    return SNMP_ERR_NOSUCHINSTANCE;
-  }
-
-  if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) {
-    /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */
-    return SNMP_ERR_NOSUCHINSTANCE;
-  }
-
-  return SNMP_ERR_NOERROR;
-}
-
-static void 
-snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next)
-{
-  err_t err;
-  struct snmp_node_instance node_instance;
-  memset(&node_instance, 0, sizeof(node_instance));
-
-  if (get_next) {
-    struct snmp_obj_id result_oid;
-    request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request,  &result_oid, &node_instance);
-
-    if (request->error_status == SNMP_ERR_NOERROR) {
-      snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len);
-    }
-  } else {
-    request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance);
-
-    if (request->error_status == SNMP_ERR_NOERROR) {
-      /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */
-      request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request);
-
-      if (request->error_status != SNMP_ERR_NOERROR) {
-        if (node_instance.release_instance != NULL) {
-          node_instance.release_instance(&node_instance);
-        }
-      }
-    }
-  }
-
-  if (request->error_status != SNMP_ERR_NOERROR)  {
-    if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
-      if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) {
-        /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */
-        vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK));
-        vb->value_len = 0;
-
-        err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb);
-        if (err == ERR_OK) {
-          /* we stored the exception in varbind -> go on */
-          request->error_status = SNMP_ERR_NOERROR;
-        } else if (err == ERR_BUF) {
-          request->error_status = SNMP_ERR_TOOBIG;
-        } else {
-          request->error_status = SNMP_ERR_GENERROR;
-        }
-      }
-    } else {
-      /* according to RFC 1157/1905, all other errors only return genError */
-      request->error_status = SNMP_ERR_GENERROR;
-    }
-  } else {
-    s16_t len = node_instance.get_value(&node_instance, vb->value);
-    vb->type = node_instance.asn1_type;
-
-    if(len >= 0) {
-      vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */
-
-      LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE);
-      err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb);
-
-      if (err == ERR_BUF) {
-        request->error_status = SNMP_ERR_TOOBIG;
-      } else if (err != ERR_OK) {
-        request->error_status = SNMP_ERR_GENERROR;
-      }
-    } else {
-      request->error_status = SNMP_ERR_GENERROR;
-    }
-
-    if (node_instance.release_instance != NULL) {
-      node_instance.release_instance(&node_instance);
-    }
-  }
-}
-
-
-/**
- * Service an internal or external event for SNMP GET.
- *
- * @param request points to the associated message process state
- */
-static err_t
-snmp_process_get_request(struct snmp_request *request)
-{
-  snmp_vb_enumerator_err_t err;
-  struct snmp_varbind vb;
-  vb.value = request->value_buffer;
-
-  LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n"));
-
-  while (request->error_status == SNMP_ERR_NOERROR) {
-    err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
-    if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
-      if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
-        snmp_process_varbind(request, &vb, 0);
-      } else {
-        request->error_status = SNMP_ERR_GENERROR;
-      }
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-      /* no more varbinds in request */
-      break;
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
-      /* malformed ASN.1, don't answer */
-      return ERR_ARG;
-    } else {
-      request->error_status = SNMP_ERR_GENERROR;
-    }
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Service an internal or external event for SNMP GET.
- *
- * @param request points to the associated message process state
- */
-static err_t
-snmp_process_getnext_request(struct snmp_request *request)
-{
-  snmp_vb_enumerator_err_t err;
-  struct snmp_varbind vb;
-  vb.value = request->value_buffer;
-
-  LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n"));
-
-  while (request->error_status == SNMP_ERR_NOERROR) {
-    err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
-    if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
-      if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
-        snmp_process_varbind(request, &vb, 1);
-      } else {
-        request->error_status = SNMP_ERR_GENERROR;
-      }
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-      /* no more varbinds in request */
-      break;
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
-      /* malformed ASN.1, don't answer */
-      return ERR_ARG;
-    } else {
-      request->error_status = SNMP_ERR_GENERROR;
-    }
-  }
-  
-  return ERR_OK;
-}
-
-/**
- * Service an internal or external event for SNMP GETBULKT.
- *
- * @param request points to the associated message process state
- */
-static err_t
-snmp_process_getbulk_request(struct snmp_request *request)
-{
-  snmp_vb_enumerator_err_t err;
-  s32_t non_repeaters     = request->non_repeaters;
-  s32_t repetitions;
-  u16_t repetition_offset = 0;
-  struct snmp_varbind_enumerator repetition_varbind_enumerator;
-  struct snmp_varbind vb;
-  vb.value = request->value_buffer;
-
-  if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) {
-    repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS);
-  } else {
-    repetitions = request->max_repetitions;
-  }
-
-  LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n"));
-
-  /* process non repeaters and first repetition */
-  while (request->error_status == SNMP_ERR_NOERROR) {
-    if (non_repeaters == 0) {
-      repetition_offset = request->outbound_pbuf_stream.offset;
-
-      if (repetitions == 0) {
-        /* do not resolve repeaters when repetitions is set to 0 */
-        break;
-      }
-      repetitions--;
-    }
-
-    err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
-    if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-      /* no more varbinds in request */
-      break;
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
-      /* malformed ASN.1, don't answer */
-      return ERR_ARG;
-    } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) {
-      request->error_status = SNMP_ERR_GENERROR;
-    } else {
-      snmp_process_varbind(request, &vb, 1);
-      non_repeaters--;
-    }
-  }
-
-  /* process repetitions > 1 */
-  while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) {
-
-    u8_t all_endofmibview = 1;
-    
-    snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset);
-    repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */
-
-    while (request->error_status == SNMP_ERR_NOERROR) {
-      vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */
-      err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb);
-      if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
-        vb.value = request->value_buffer;
-        snmp_process_varbind(request, &vb, 1);
-
-        if (request->error_status != SNMP_ERR_NOERROR) {
-          /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */
-          request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
-        } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) {
-          all_endofmibview = 0;
-        }
-      } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-        /* no more varbinds in request */
-        break;
-      } else {
-        LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!"));
-        request->error_status = SNMP_ERR_GENERROR;
-        request->error_index  = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
-      }
-    }
-
-    if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) {
-      /* stop when all varbinds in a loop return EndOfMibView */
-      break;
-    }
-    
-    repetitions--;
-  }
-
-  if (request->error_status == SNMP_ERR_TOOBIG) {
-    /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */
-    request->error_status = SNMP_ERR_NOERROR;
-  }
-
-  return ERR_OK;
-}
-
-/**
- * Service an internal or external event for SNMP SET.
- *
- * @param request points to the associated message process state
- */
-static err_t
-snmp_process_set_request(struct snmp_request *request)
-{
-  snmp_vb_enumerator_err_t err;
-  struct snmp_varbind vb;
-  vb.value = request->value_buffer;
-
-  LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n"));
-
-  /* perform set test on all objects */
-  while (request->error_status == SNMP_ERR_NOERROR) {
-    err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
-    if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
-      struct snmp_node_instance node_instance;
-      memset(&node_instance, 0, sizeof(node_instance));
-      
-      request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
-      if (request->error_status == SNMP_ERR_NOERROR) {
-        if (node_instance.asn1_type != vb.type) {
-          request->error_status = SNMP_ERR_WRONGTYPE;
-        } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) {
-          request->error_status = SNMP_ERR_NOTWRITABLE;
-        } else {
-          if (node_instance.set_test != NULL) {
-            request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value);
-          }
-        }
-
-        if (node_instance.release_instance != NULL) {
-          node_instance.release_instance(&node_instance);
-        }
-      }
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-      /* no more varbinds in request */
-      break;
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) {
-      request->error_status = SNMP_ERR_WRONGLENGTH;
-    } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
-      /* malformed ASN.1, don't answer */
-      return ERR_ARG;
-    } else {
-      request->error_status = SNMP_ERR_GENERROR;
-    }
-  }
-
-  /* perform real set operation on all objects */
-  if (request->error_status == SNMP_ERR_NOERROR) {
-    snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
-    while (request->error_status == SNMP_ERR_NOERROR) {
-      err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
-      if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
-        struct snmp_node_instance node_instance;
-        memset(&node_instance, 0, sizeof(node_instance));
-        request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
-        if (request->error_status == SNMP_ERR_NOERROR) {
-          if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) {
-            if (request->inbound_varbind_enumerator.varbind_count == 1) {
-              request->error_status = SNMP_ERR_COMMITFAILED;
-            } else {
-              /* we cannot undo the set operations done so far */
-              request->error_status = SNMP_ERR_UNDOFAILED;
-            }
-          }
-
-          if (node_instance.release_instance != NULL) {
-            node_instance.release_instance(&node_instance);
-          }
-        }
-      } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
-        /* no more varbinds in request */
-        break;
-      } else {
-        /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */
-        request->error_status = SNMP_ERR_GENERROR;
-      }
-    }
-  }
-
-  return ERR_OK;
-}
-
-#define PARSE_EXEC(code, retValue) \
-  if ((code) != ERR_OK) { \
-    LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \
-    snmp_stats.inasnparseerrs++; \
-    return retValue; \
-  }
-
-#define PARSE_ASSERT(cond, retValue) \
-  if (!(cond)) { \
-    LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \
-    snmp_stats.inasnparseerrs++; \
-    return retValue; \
-  }
-
-#define BUILD_EXEC(code, retValue) \
-  if ((code) != ERR_OK) { \
-    LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \
-    return retValue; \
-  }
-
-#define IF_PARSE_EXEC(code)   PARSE_EXEC(code, ERR_ARG)
-#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG)
-
-/**
- * Checks and decodes incoming SNMP message header, logs header errors.
- *
- * @param request points to the current message request state return
- * @return
- * - ERR_OK SNMP header is sane and accepted
- * - ERR_VAL SNMP header is either malformed or rejected
- */
-static err_t
-snmp_parse_inbound_frame(struct snmp_request *request)
-{
-  struct snmp_pbuf_stream pbuf_stream;
-  struct snmp_asn1_tlv tlv;
-  s32_t parent_tlv_value_len;
-  s32_t s32_value;
-  err_t err;
-
-  IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
-  
-  /* decode main container consisting of version, community and PDU */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length));
-  parent_tlv_value_len = tlv.value_len;
-
-  /* decode version */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-  parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-  IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-  
-  IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-  if ((s32_value != SNMP_VERSION_1) &&
-      (s32_value != SNMP_VERSION_2c)
-#if LWIP_SNMP_V3
-      && (s32_value != SNMP_VERSION_3)
-#endif
-     )
-  {
-    /* unsupported SNMP version */
-    snmp_stats.inbadversions++;
-    return ERR_ARG;
-  }
-  request->version = (u8_t)s32_value;
-
-#if LWIP_SNMP_V3
-  if (request->version == SNMP_VERSION_3) {
-    u16_t u16_value;
-    u16_t inbound_msgAuthenticationParameters_offset;
-
-    /* SNMPv3 doesn't use communities */
-    /* @todo: Differentiate read/write access */
-    strcpy((char*)request->community, snmp_community);
-    request->community_strlen = (u16_t)strlen(snmp_community);
-
-    /* RFC3414 globalData */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    /* decode msgID */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-    request->msg_id = s32_value;
-
-    /* decode msgMaxSize */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-    request->msg_max_size = s32_value;
-
-    /* decode msgFlags */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-    request->msg_flags = (u8_t)s32_value;
-
-    /* decode msgSecurityModel */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-    request->msg_security_model = s32_value;
-
-    /* RFC3414 msgSecurityParameters
-     * The User-based Security Model defines the contents of the OCTET
-     * STRING as a SEQUENCE.
-     *
-     * We skip the protective dummy OCTET STRING header
-     * to access the SEQUENCE header.
-     */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    /* msgSecurityParameters SEQUENCE header */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    /* decode msgAuthoritativeEngineID */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id,
-        &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
-    request->msg_authoritative_engine_id_len = (u8_t)u16_value;
-
-    /* msgAuthoritativeEngineBoots */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots));
-
-    /* msgAuthoritativeEngineTime */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time));
-    /* @todo: Implement time window checking */
-
-    /* msgUserName */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name,
-        &u16_value, SNMP_V3_MAX_USER_LENGTH));
-    request->msg_user_name_len = (u8_t)u16_value;
-    /* @todo: Implement unknown user error response */
-    IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL));
-
-    /* msgAuthenticationParameters */
-    memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-    /* Remember position */
-    inbound_msgAuthenticationParameters_offset = pbuf_stream.offset;
-    LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset);
-    /* Read auth parameters */
-    IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters,
-        &u16_value, tlv.value_len));
-
-#if LWIP_SNMP_V3_CRYPTO
-    if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
-      const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 };
-      u8_t key[20];
-      u8_t algo;
-      u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)];
-      struct snmp_pbuf_stream auth_stream;
-
-      /* Rewind stream */
-      IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
-      IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset));
-      /* Set auth parameters to zero for verification */
-      IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len));
-
-      /* Verify authentication */
-      IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
-
-      IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL));
-      IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac));
-      /* @todo: Implement error response */
-      IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
-    }
-#else
-    /* Ungraceful exit if we encounter cryptography and don't support it.
-     * @todo: Implement error response
-     */
-    IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)));
-#endif
-
-    /* msgPrivacyParameters */
-    memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH);
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters,
-        &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH));
-
-#if LWIP_SNMP_V3_CRYPTO
-    /* Decrypt message */
-    if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
-      u8_t key[20];
-      u8_t algo;
-
-      IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-      IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-      parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
-      IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-      IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key));
-      IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key,
-          request->msg_privacy_parameters, request->msg_authoritative_engine_boots,
-          request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT));
-    }
-#endif
-
-    /* Scoped PDU
-     * Encryption context
-     */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    /* contextEngineID */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id,
-        &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
-    request->context_engine_id_len = (u8_t)u16_value;
-
-    /* contextName */
-    IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-    IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-    parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-    IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-    IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name,
-        &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
-    request->context_name_len = (u8_t)u16_value;
-  } else
-#endif
-  {
-  /* decode community */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
-  parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-  IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-  err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN);
-  if (err == ERR_MEM) {
-    /* community string does not fit in our buffer -> its too long -> its invalid */
-    request->community_strlen = 0;
-    snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len);
-  } else {
-    IF_PARSE_ASSERT(err == ERR_OK);
-  }
-  /* add zero terminator */
-  request->community[request->community_strlen] = 0;
-  }
-
-  /* decode PDU type (next container level) */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length);
-  request->inbound_padding_len = pbuf_stream.length - tlv.value_len;
-  parent_tlv_value_len = tlv.value_len;
-
-  /* validate PDU type */
-  switch(tlv.type) {
-    case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ):
-      /* GetRequest PDU */
-      snmp_stats.ingetrequests++;
-      break;
-    case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ):
-      /* GetNextRequest PDU */
-      snmp_stats.ingetnexts++;
-      break;
-    case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ):
-      /* GetBulkRequest PDU */
-      if (request->version < SNMP_VERSION_2c) {
-        /* RFC2089: invalid, drop packet */
-        return ERR_ARG;
-      }
-      break;
-    case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ):
-      /* SetRequest PDU */
-      snmp_stats.insetrequests++;
-      break;
-    default:
-      /* unsupported input PDU for this agent (no parse error) */
-      LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \
-      return ERR_ARG;
-      break;
-  }
-  request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK;
-
-  /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */
-  if (request->community_strlen == 0) {
-    /* community string was too long or really empty*/
-    snmp_stats.inbadcommunitynames++;
-    snmp_authfail_trap();
-    return ERR_ARG;
-  } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
-    if (snmp_community_write[0] == 0) {
-      /* our write community is empty, that means all our objects are readonly */
-      request->error_status = SNMP_ERR_NOTWRITABLE;
-      request->error_index  = 1;
-    } else if (strncmp(snmp_community_write, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) {
-      /* community name does not match */
-      snmp_stats.inbadcommunitynames++;
-      snmp_authfail_trap();
-      return ERR_ARG;
-    }
-  } else { 
-    if (strncmp(snmp_community, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) {
-      /* community name does not match */
-      snmp_stats.inbadcommunitynames++;
-      snmp_authfail_trap();
-      return ERR_ARG;
-    }
-  }
-  
-  /* decode request ID */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-  parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-  IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-  
-  IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id));
-
-  /* decode error status / non-repeaters */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-  parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-  IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-  if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters));
-    if (request->non_repeaters < 0) {
-      /* RFC 1905, 4.2.3 */
-      request->non_repeaters = 0;
-    }
-  } else {
-    /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
-    IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR);
-  }
-
-  /* decode error index / max-repetitions */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
-  parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-  IF_PARSE_ASSERT(parent_tlv_value_len > 0);
-
-  if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions));
-    if (request->max_repetitions < 0) {
-      /* RFC 1905, 4.2.3 */
-      request->max_repetitions = 0;
-    }
-  } else {
-    IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index));
-    IF_PARSE_ASSERT(s32_value == 0);
-  }
-
-  /* decode varbind-list type (next container level) */
-  IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
-  IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length));
-  
-  request->inbound_varbind_offset = pbuf_stream.offset;
-  request->inbound_varbind_len    = pbuf_stream.length - request->inbound_padding_len;
-  snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
-
-  return ERR_OK;
-}
-
-#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG)
-
-static err_t
-snmp_prepare_outbound_frame(struct snmp_request *request)
-{
-  struct snmp_asn1_tlv tlv;
-  struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream);
-
-  /* try allocating pbuf(s) for maximum response size */
-  request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM);
-  if (request->outbound_pbuf == NULL) {
-    return ERR_MEM;
-  }
-
-  snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len);
-
-  /* 'Message' sequence */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
-  OF_BUILD_EXEC( 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(request->version, &tlv.value_len);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-  OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) );
-
-#if LWIP_SNMP_V3
-  if (request->version < SNMP_VERSION_3) {
-#endif
-  /* community */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-  OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) );
-#if LWIP_SNMP_V3
-  } else {
-    const char* id;
-
-    /* globalData */
-    request->outbound_msg_global_data_offset = pbuf_stream->offset;
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-    /* msgID */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
-    snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id));
-
-    /* msgMaxSize */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
-    snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size));
-
-    /* msgFlags */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1));
-
-    /* msgSecurityModel */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
-    snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model));
-
-    /* end of msgGlobalData */
-    request->outbound_msg_global_data_end = pbuf_stream->offset;
-
-    /* msgSecurityParameters */
-    request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset;
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-    request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset;
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-    /* msgAuthoritativeEngineID */
-    snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len);
-    MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len);
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len));
-
-    request->msg_authoritative_engine_time = snmpv3_get_engine_time();
-    request->msg_authoritative_engine_boots = snmpv3_get_engine_boots();
-
-    /* msgAuthoritativeEngineBoots */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
-    snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots));
-
-    /* msgAuthoritativeEngineTime */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
-    snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time));
-
-    /* msgUserName */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len));
-
-#if LWIP_SNMP_V3_CRYPTO
-    /* msgAuthenticationParameters */
-    if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
-      memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-      request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset;
-      SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-      OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-      OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
-    } else
-#endif
-    {
-      SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
-      OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    }
-
-#if LWIP_SNMP_V3_CRYPTO
-    /* msgPrivacyParameters */
-    if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
-      snmpv3_build_priv_param(request->msg_privacy_parameters);
-
-      SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH);
-      OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-      OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH));
-    } else
-#endif
-    {
-      SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
-      OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-    }
-
-    /* End of msgSecurityParameters, so we can calculate the length of this sequence later */
-    request->outbound_msg_security_parameters_end = pbuf_stream->offset;
-
-#if LWIP_SNMP_V3_CRYPTO
-    /* For encryption we have to encapsulate the payload in an octet string */
-    if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
-      request->outbound_scoped_pdu_string_offset = pbuf_stream->offset;
-      SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0);
-      OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    }
-#endif
-    /* Scoped PDU
-     * Encryption context
-     */
-    request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset;
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-    /* contextEngineID */
-    snmpv3_get_engine_id(&id, &request->context_engine_id_len);
-    MEMCPY(request->context_engine_id, id, request->context_engine_id_len);
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len));
-
-    /* contextName */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len));
-  }
-#endif
-
-  /* 'PDU' sequence */
-  request->outbound_pdu_offset = pbuf_stream->offset;
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-
-  /* request ID */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
-  snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-  OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) );
-
-  /* error status */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-  request->outbound_error_status_offset = pbuf_stream->offset;
-  OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
-
-  /* error index */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-  request->outbound_error_index_offset = pbuf_stream->offset;
-  OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
-
-  /* 'VarBindList' sequence */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
-
-  request->outbound_varbind_offset = pbuf_stream->offset;
-
-  return ERR_OK;
-}
-
-/** Calculate the length of a varbind list */
-err_t
-snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len)
-{
-  /* calculate required lengths */
-  snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len);
-  snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len);
-
-  if (varbind->value_len == 0) {
-    len->value_value_len = 0;
-  } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
-    len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA);
-  } else {
-    switch (varbind->type) {
-      case SNMP_ASN1_TYPE_INTEGER:
-        if (varbind->value_len != sizeof (s32_t)) {
-          return ERR_VAL;
-        }
-        snmp_asn1_enc_s32t_cnt(*((s32_t*) varbind->value), &len->value_value_len);
-        break;
-      case SNMP_ASN1_TYPE_COUNTER:
-      case SNMP_ASN1_TYPE_GAUGE:
-      case SNMP_ASN1_TYPE_TIMETICKS:
-        if (varbind->value_len != sizeof (u32_t)) {
-          return ERR_VAL;
-        }
-        snmp_asn1_enc_u32t_cnt(*((u32_t*) varbind->value), &len->value_value_len);
-        break;
-      case SNMP_ASN1_TYPE_OCTET_STRING:
-      case SNMP_ASN1_TYPE_IPADDR:
-      case SNMP_ASN1_TYPE_OPAQUE:
-        len->value_value_len = varbind->value_len;
-        break;
-      case SNMP_ASN1_TYPE_NULL:
-        if (varbind->value_len != 0) {
-          return ERR_VAL;
-        }
-        len->value_value_len = 0;
-        break;
-      case SNMP_ASN1_TYPE_OBJECT_ID:
-        if ((varbind->value_len & 0x03) != 0) {
-          return ERR_VAL;
-        }
-        snmp_asn1_enc_oid_cnt((u32_t*) varbind->value, varbind->value_len >> 2, &len->value_value_len);
-        break;
-      case SNMP_ASN1_TYPE_COUNTER64:
-        if (varbind->value_len != (2 * sizeof (u32_t))) {
-          return ERR_VAL;
-        }
-        snmp_asn1_enc_u64t_cnt((u32_t*) varbind->value, &len->value_value_len);
-        break;
-      default:
-        /* unsupported type */
-        return ERR_VAL;
-    }
-  }
-  snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len);
-
-  len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len;
-  snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len);
-
-  return ERR_OK;
-}
-
-#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG)
-
-err_t
-snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind)
-{
-  struct snmp_asn1_tlv tlv;
-  struct snmp_varbind_len len;
-  err_t err;
-
-  err = snmp_varbind_length(varbind, &len);
-
-  if (err != ERR_OK) {
-    return err;
-  }
-
-  /* check length already before adding first data because in case of GetBulk,
-   *  data added so far is returned and therefore no partial data shall be added
-   */
-  if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) {
-    return ERR_BUF;
-  }
-
-  /* 'VarBind' sequence */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len);
-  OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-  /* VarBind OID */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len);
-  OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-  OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len));
-
-  /* VarBind value */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len);
-  OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
-
-  if (len.value_value_len > 0) {
-    if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
-      OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len));
-    } else {
-      switch (varbind->type) {
-        case SNMP_ASN1_TYPE_INTEGER:
-          OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t*) varbind->value)));
-          break;
-        case SNMP_ASN1_TYPE_COUNTER:
-        case SNMP_ASN1_TYPE_GAUGE:
-        case SNMP_ASN1_TYPE_TIMETICKS:
-          OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t*) varbind->value)));
-          break;
-        case SNMP_ASN1_TYPE_OCTET_STRING:
-        case SNMP_ASN1_TYPE_IPADDR:
-        case SNMP_ASN1_TYPE_OPAQUE:
-          OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len));
-          len.value_value_len = varbind->value_len;
-          break;
-        case SNMP_ASN1_TYPE_OBJECT_ID:
-          OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t*) varbind->value, varbind->value_len / sizeof (u32_t)));
-          break;
-        case SNMP_ASN1_TYPE_COUNTER64:
-          OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, (u32_t*) varbind->value));
-          break;
-        default:
-          LWIP_ASSERT("Unknown variable type", 0);
-          break;
-      }
-    }
-  }
-
-  return ERR_OK;
-}
-
-static err_t
-snmp_complete_outbound_frame(struct snmp_request *request)
-{
-  struct snmp_asn1_tlv tlv;
-  u16_t frame_size;
-  u8_t outbound_padding = 0;
-
-  if (request->version == SNMP_VERSION_1) {
-    if (request->error_status != SNMP_ERR_NOERROR) {
-      /* map v2c error codes to v1 compliant error code (according to RFC 2089) */
-      switch (request->error_status) {
-        /* mapping of implementation specific "virtual" error codes 
-         * (during processing of frame we already stored them in error_status field, 
-         * so no need to check all varbinds here for those exceptions as suggested by RFC) */
-        case SNMP_ERR_NOSUCHINSTANCE:
-        case SNMP_ERR_NOSUCHOBJECT:
-        case SNMP_ERR_ENDOFMIBVIEW:
-          request->error_status = SNMP_ERR_NOSUCHNAME;
-          break;
-        /* mapping according to RFC */
-        case SNMP_ERR_WRONGVALUE:
-        case SNMP_ERR_WRONGENCODING:
-        case SNMP_ERR_WRONGTYPE:
-        case SNMP_ERR_WRONGLENGTH:
-        case SNMP_ERR_INCONSISTENTVALUE:
-          request->error_status = SNMP_ERR_BADVALUE;
-          break;
-        case SNMP_ERR_NOACCESS:
-        case SNMP_ERR_NOTWRITABLE:
-        case SNMP_ERR_NOCREATION:
-        case SNMP_ERR_INCONSISTENTNAME:
-        case SNMP_ERR_AUTHORIZATIONERROR:
-          request->error_status = SNMP_ERR_NOSUCHNAME;
-          break;
-        case SNMP_ERR_RESOURCEUNAVAILABLE:
-        case SNMP_ERR_COMMITFAILED:
-        case SNMP_ERR_UNDOFAILED:
-        default:
-          request->error_status = SNMP_ERR_GENERROR;
-          break;
-       }
-    }
-  } else {
-    if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
-      /* map error codes to according to RFC 1905 (4.2.5.  The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */
-      switch (request->error_status) {
-        case SNMP_ERR_NOSUCHINSTANCE:
-        case SNMP_ERR_NOSUCHOBJECT:
-        case SNMP_ERR_ENDOFMIBVIEW:
-          request->error_status = SNMP_ERR_NOTWRITABLE;
-          break;
-        default:
-          break;
-      }
-    }
-
-    if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
-      /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */
-      LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
-      return ERR_ARG;
-    }
-  }
-
-  if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) {
-    /* all inbound vars are returned in response without any modification for error responses and successful set requests*/
-    struct snmp_pbuf_stream inbound_stream;
-    OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) );
-    OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) );
-    snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0);
-  }
-
-  frame_size = request->outbound_pbuf_stream.offset;
-
-#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
-  /* Calculate padding for encryption */
-  if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
-    u8_t i;
-    outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07;
-    for (i = 0; i < outbound_padding; i++) {
-      snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0);
-    }
-  }
-#endif
-
-  /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
-  OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) );
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
-
-#if LWIP_SNMP_V3
-  if (request->version == SNMP_VERSION_3) {
-    /* complete missing length in 'globalData' sequence */
-    /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end
-        - request->outbound_msg_global_data_offset - 1 - 1);
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset));
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
-
-    /* complete missing length in 'msgSecurityParameters' sequence */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end
-        - request->outbound_msg_security_parameters_str_offset - 1 - 1);
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset));
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
-
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end
-        - request->outbound_msg_security_parameters_seq_offset - 1 - 1);
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset));
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
-
-    /* complete missing length in scoped PDU sequence */
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3);
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset));
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
-  }
-#endif
-
-  /* complete missing length in 'PDU' sequence */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3,
-      frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
-  OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) );
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
-
-  /* process and encode final error status */
-  if (request->error_status != 0) {
-    u16_t len;
-    snmp_asn1_enc_s32t_cnt(request->error_status, &len);
-    if (len != 1) {
-      /* error, we only reserved one byte for it */
-      return ERR_ARG;
-    }
-    OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) );
-    OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) );
-
-    /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */
-    switch (request->error_status) {
-      case SNMP_ERR_TOOBIG:
-        snmp_stats.outtoobigs++;
-        break;
-      case SNMP_ERR_NOSUCHNAME:
-        snmp_stats.outnosuchnames++;
-        break;
-      case SNMP_ERR_BADVALUE:
-        snmp_stats.outbadvalues++;
-        break;
-      case SNMP_ERR_GENERROR:
-      default:
-        snmp_stats.outgenerrs++;
-        break;
-    }
-
-    if (request->error_status == SNMP_ERR_TOOBIG) {
-      request->error_index = 0; /* defined by RFC 1157 */
-    } else if (request->error_index == 0) {
-      /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */
-      request->error_index = request->inbound_varbind_enumerator.varbind_count;
-    }
-  } else {
-    if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
-      snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count;
-    } else {
-      snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count;
-    }
-  }
-
-  /* encode final error index*/
-  if (request->error_index != 0) {
-    u16_t len;
-    snmp_asn1_enc_s32t_cnt(request->error_index, &len);
-    if (len != 1) {
-      /* error, we only reserved one byte for it */
-      return ERR_VAL;
-    }
-    OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) );
-    OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) );
-  }
-
-  /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */
-  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset);
-  OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
-  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
-
-  /* Authenticate response */
-#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
-  /* Encrypt response */
-  if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
-    u8_t key[20];
-    u8_t algo;
-
-    /* complete missing length in PDU sequence */
-    OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset));
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding
-        - request->outbound_scoped_pdu_string_offset - 1 - 3);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
-
-    OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key));
-
-    OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key,
-        request->msg_privacy_parameters, request->msg_authoritative_engine_boots,
-        request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT));
-  }
-
-  if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) {
-    u8_t key[20];
-    u8_t algo;
-    u8_t hmac[20];
-
-    OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL));
-    OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream),
-        request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
-    OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac));
-
-    MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-    OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream,
-                  request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
-    OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream,
-                  request->outbound_msg_authentication_parameters_offset));
-
-    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
-    OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv));
-    OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream,
-                  request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
-  }
-#endif
-
-  pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding);
-
-  snmp_stats.outgetresponses++;
-  snmp_stats.outpkts++;
-
-  return ERR_OK;
-}
-
-static void 
-snmp_execute_write_callbacks(struct snmp_request *request)
-{
-  struct snmp_varbind_enumerator inbound_varbind_enumerator;
-  struct snmp_varbind vb;
-
-  snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
-  vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */
-
-  while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) {
-    snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg);
-  }
-}
-
-
-/* ----------------------------------------------------------------------- */
-/* VarBind enumerator methods */
-/* ----------------------------------------------------------------------- */
-
-void
-snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length)
-{
-  snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length);
-  enumerator->varbind_count = 0;
-}
-
-#define VB_PARSE_EXEC(code)   PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR)
-#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR)
-
-snmp_vb_enumerator_err_t
-snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind)
-{
-  struct snmp_asn1_tlv tlv;
-  u16_t  varbind_len;
-  err_t  err;
-  
-  if (enumerator->pbuf_stream.length == 0)
-  {
-    return SNMP_VB_ENUMERATOR_ERR_EOVB;
-  }
-  enumerator->varbind_count++;
-
-  /* decode varbind itself (parent container of a varbind) */
-  VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
-  VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length));
-  varbind_len = tlv.value_len;
-
-  /* decode varbind name (object id) */
-  VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
-  VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length));
-   
-  VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN));
-  varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv);
-
-  /* decode varbind value (object id) */
-  VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
-  VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length));
-  varbind->type = tlv.type;
-
-  /* shall the value be decoded ? */
-  if (varbind->value != NULL) {
-    switch (varbind->type) {
-      case SNMP_ASN1_TYPE_INTEGER:
-        VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t*)varbind->value));
-        varbind->value_len = sizeof(s32_t*);
-        break;
-      case SNMP_ASN1_TYPE_COUNTER:
-      case SNMP_ASN1_TYPE_GAUGE:
-      case SNMP_ASN1_TYPE_TIMETICKS:
-        VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value));
-        varbind->value_len = sizeof(u32_t*);
-        break;
-      case SNMP_ASN1_TYPE_OCTET_STRING:
-      case SNMP_ASN1_TYPE_OPAQUE:
-        err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE);
-        if (err == ERR_MEM) {
-          return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
-        }
-        VB_PARSE_ASSERT(err == ERR_OK);
-        break;
-      case SNMP_ASN1_TYPE_NULL:
-        varbind->value_len = 0;
-        break;
-      case SNMP_ASN1_TYPE_OBJECT_ID:
-        /* misuse tlv.length_len as OID_length transporter */
-        err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN);
-        if (err == ERR_MEM) {
-          return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
-        }
-        VB_PARSE_ASSERT(err == ERR_OK);
-        varbind->value_len = tlv.length_len * sizeof(u32_t);
-        break;
-      case SNMP_ASN1_TYPE_IPADDR:
-        if (tlv.value_len == 4) {
-          /* must be exactly 4 octets! */
-          VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE));
-        } else {
-          VB_PARSE_ASSERT(0);
-        }
-        break;
-      case SNMP_ASN1_TYPE_COUNTER64:
-        VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value));
-        varbind->value_len = 2 * sizeof(u32_t*);
-        break;
-      default:
-        VB_PARSE_ASSERT(0);
-        break;
-    }
-  } else {
-    snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len);
-    varbind->value_len = tlv.value_len;
-  }
-
-  return SNMP_VB_ENUMERATOR_ERR_OK;
-}
-
-#endif /* LWIP_SNMP */

+ 0 - 194
components/net/lwip-2.0.0/src/apps/snmp/snmp_msg.h

@@ -1,194 +0,0 @@
-/**
- * @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 */

+ 0 - 120
components/net/lwip-2.0.0/src/apps/snmp/snmp_netconn.c

@@ -1,120 +0,0 @@
-/**
- * @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 "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 */

+ 0 - 156
components/net/lwip-2.0.0/src/apps/snmp/snmp_pbuf_stream.c

@@ -1,156 +0,0 @@
-/**
- * @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 */

+ 0 - 73
components/net/lwip-2.0.0/src/apps/snmp/snmp_pbuf_stream.h

@@ -1,73 +0,0 @@
-/**
- * @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 */

+ 0 - 100
components/net/lwip-2.0.0/src/apps/snmp/snmp_raw.c

@@ -1,100 +0,0 @@
-/**
- * @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 */

+ 0 - 220
components/net/lwip-2.0.0/src/apps/snmp/snmp_scalar.c

@@ -1,220 +0,0 @@
-/**
- * @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 */

+ 0 - 343
components/net/lwip-2.0.0/src/apps/snmp/snmp_table.c

@@ -1,343 +0,0 @@
-/**
- * @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 */

+ 0 - 218
components/net/lwip-2.0.0/src/apps/snmp/snmp_threadsync.c

@@ -1,218 +0,0 @@
-/**
- * @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_ASSERT("Failed to set up semaphore", err == ERR_OK);
-  instance->sync_fn = sync_fn;
-}
-
-#endif /* LWIP_SNMP */

+ 0 - 445
components/net/lwip-2.0.0/src/apps/snmp/snmp_traps.c

@@ -1,445 +0,0 @@
-/**
- * @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 */

+ 0 - 136
components/net/lwip-2.0.0/src/apps/snmp/snmpv3.c

@@ -1,136 +0,0 @@
-/**
- * @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

+ 0 - 145
components/net/lwip-2.0.0/src/apps/snmp/snmpv3_dummy.c

@@ -1,145 +0,0 @@
-/**
- * @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 */

+ 0 - 331
components/net/lwip-2.0.0/src/apps/snmp/snmpv3_mbedtls.c

@@ -1,331 +0,0 @@
-/**
- * @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 */

+ 0 - 66
components/net/lwip-2.0.0/src/apps/snmp/snmpv3_priv.h

@@ -1,66 +0,0 @@
-/**
- * @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 */

+ 0 - 726
components/net/lwip-2.0.0/src/apps/sntp/sntp.c

@@ -1,726 +0,0 @@
-/**
- * @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);
-    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 IP4_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 */

+ 0 - 417
components/net/lwip-2.0.0/src/apps/tftp/tftp_server.c

@@ -1,417 +0,0 @@
-/****************************************************************//**
- *
- * @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 */

+ 0 - 35
components/net/lwip-2.0.0/src/arch/include/arch/bpstruct.h

@@ -1,35 +0,0 @@
-/*
- * 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>
- *
- */
-
-#if defined(__ICCARM__)
-#pragma pack(1)
-#endif

+ 0 - 105
components/net/lwip-2.0.0/src/arch/include/arch/cc.h

@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- * $Id: cc.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $
- */
-#ifndef __ARCH_CC_H__
-#define __ARCH_CC_H__
-
-#include <rthw.h>
-#include <rtthread.h>
-
-#define U16_F "hu"
-#define S16_F "hd"
-#define X16_F "hx"
-#define U32_F "lu"
-#define S32_F "ld"
-#define X32_F "lx"
-
-#ifdef RT_USING_LIBC
-#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__)
-#include <sys/errno.h>
-#else
-#include <errno.h>
-/* some errno not defined in newlib */
-#define ENSRNOTFOUND 163  /* Domain name not found */
-/* WARNING: ESHUTDOWN also not defined in newlib. We chose
-			180 here because the number "108" which is used
-			in arch.h has been assigned to another error code. */
-#define ESHUTDOWN 180
-#endif /* __CC_ARM/__IAR_SYSTEMS_ICC__ */
-#else
-#define LWIP_PROVIDE_ERRNO
-#endif
-
-#ifdef RT_USING_LIBC
-#include <sys/time.h>
-#define LWIP_TIMEVAL_PRIVATE	   0
-#else
-#define LWIP_TIMEVAL_PRIVATE	   1
-#endif
-
-#if defined(__CC_ARM)   /* ARMCC compiler */
-#define PACK_STRUCT_FIELD(x) x
-#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
-#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_END
-#elif defined(__IAR_SYSTEMS_ICC__)   /* IAR Compiler */
-#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_STRUCT
-#define PACK_STRUCT_END
-#define PACK_STRUCT_FIELD(x) x
-#define PACK_STRUCT_USE_INCLUDES
-#elif defined(__GNUC__)     /* GNU GCC Compiler */
-#define PACK_STRUCT_FIELD(x) x
-#define PACK_STRUCT_STRUCT __attribute__((packed))
-#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_END
-#elif defined(_MSC_VER)
-#define PACK_STRUCT_FIELD(x) x
-#define PACK_STRUCT_STRUCT
-#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_END
-#endif
-
-void sys_arch_assert(const char* file, int line);
-#define LWIP_PLATFORM_DIAG(x)	do {rt_kprintf x;} while(0)
-#define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0)
-
-#include "string.h"
-
-#define SYS_ARCH_DECL_PROTECT(level)	
-#define SYS_ARCH_PROTECT(level)		rt_enter_critical()
-#define SYS_ARCH_UNPROTECT(level) 	rt_exit_critical()
-
-#endif /* __ARCH_CC_H__ */
-

+ 0 - 35
components/net/lwip-2.0.0/src/arch/include/arch/epstruct.h

@@ -1,35 +0,0 @@
-/*
- * 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>
- *
- */
-
-#if defined(__ICCARM__)
-#pragma pack()
-#endif

+ 0 - 52
components/net/lwip-2.0.0/src/arch/include/arch/perf.h

@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- * $Id: perf.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $
- */
-#ifndef __ARCH_PERF_H__
-#define __ARCH_PERF_H__
-
-//#include <sys/times.h>
-
-#define PERF_START    /* null definition */
-#define PERF_STOP(x)  /* null definition */
-
-/*
-void perf_print(unsigned long c1l, unsigned long c1h,
-		unsigned long c2l, unsigned long c2h,
-		char *key);
-
-void perf_print_times(struct tms *start, struct tms *end, char *key);
-
-void perf_init(char *fname);
-*/
-#endif /* __ARCH_PERF_H__ */

+ 0 - 62
components/net/lwip-2.0.0/src/arch/include/arch/sys_arch.h

@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- * $Id: sys_arch.h,v 1.3 2005/03/13 16:03:23 bear Exp $
- */
-#ifndef __ARCH_SYS_ARCH_H__
-#define __ARCH_SYS_ARCH_H__
-
-#include "arch/cc.h"
-
-#include <rtthread.h>
-
-#ifndef BYTE_ORDER
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-
-#define SYS_MBOX_NULL RT_NULL
-#define SYS_SEM_NULL  RT_NULL
-
-typedef u32_t sys_prot_t;
-
-#define SYS_MBOX_SIZE 10
-#define SYS_LWIP_TIMER_NAME "timer"
-#define SYS_LWIP_MBOX_NAME "mbox"
-#define SYS_LWIP_SEM_NAME "sem"
-#define SYS_LWIP_MUTEX_NAME "mu"
-
-typedef rt_sem_t sys_sem_t;
-typedef rt_mutex_t sys_mutex_t;
-typedef rt_mailbox_t  sys_mbox_t;
-typedef rt_thread_t sys_thread_t;
-
-#endif /* __ARCH_SYS_ARCH_H__ */

+ 0 - 732
components/net/lwip-2.0.0/src/arch/sys_arch.c

@@ -1,732 +0,0 @@
-/*
- * File      : sys_arch.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2012-12-8      Bernard      add file header
- *                             export bsd socket symbol for RT-Thread Application Module 
- */
-
-#include <rtthread.h>
-
-#include "lwip/sys.h"
-#include "lwip/opt.h"
-#include "lwip/stats.h"
-#include "lwip/err.h"
-#include "arch/sys_arch.h"
-#include "lwip/debug.h"
-#include "lwip/netif.h"
-#include "lwip/tcpip.h"
-#include "netif/ethernetif.h"
-#include "lwip/sio.h"
-#include "lwip/init.h"
-#include "lwip/dhcp.h"
-
-#include <string.h>
-
-/*
- * Initialize the network interface device
- *
- * @return the operation status, ERR_OK on OK, ERR_IF on error
- */
-static err_t netif_device_init(struct netif *netif)
-{
-    struct eth_device *ethif;
-
-    ethif = (struct eth_device *)netif->state;
-    if (ethif != RT_NULL)
-    {
-        rt_device_t device;
-
-        /* get device object */
-        device = (rt_device_t) ethif;
-        if (rt_device_init(device) != RT_EOK)
-        {
-            return ERR_IF;
-        }
-
-        /* copy device flags to netif flags */
-        netif->flags = ethif->flags;
-
-        return ERR_OK;
-    }
-
-    return ERR_IF;
-}
-/*
- * Initialize the ethernetif layer and set network interface device up
- */
-static void tcpip_init_done_callback(void *arg)
-{
-    rt_device_t device;
-    struct eth_device *ethif;
-    ip_addr_t ipaddr, netmask, gw;
-    struct rt_list_node* node;
-    struct rt_object* object;
-    struct rt_object_information *information;
-
-    extern struct rt_object_information rt_object_container[];
-
-    LWIP_ASSERT("invalid arg.\n",arg);
-
-    IP4_ADDR(&gw, 0,0,0,0);
-    IP4_ADDR(&ipaddr, 0,0,0,0);
-    IP4_ADDR(&netmask, 0,0,0,0);
-
-    /* enter critical */
-    rt_enter_critical();
-
-    /* for each network interfaces */
-    information = &rt_object_container[RT_Object_Class_Device];
-    for (node = information->object_list.next;
-         node != &(information->object_list);
-         node = node->next)
-    {
-        object = rt_list_entry(node, struct rt_object, list);
-        device = (rt_device_t)object;
-        if (device->type == RT_Device_Class_NetIf)
-        {
-            ethif = (struct eth_device *)device;
-
-            /* leave critical */
-            rt_exit_critical();
-
-            netif_add(ethif->netif, &ipaddr, &netmask, &gw,
-                      ethif, netif_device_init, tcpip_input);
-
-            if (netif_default == RT_NULL)
-                netif_set_default(ethif->netif);
-
-#if LWIP_DHCP
-            /* set interface up */
-            netif_set_up(ethif->netif);
-            /* if this interface uses DHCP, start the DHCP client */
-            dhcp_start(ethif->netif);
-#else
-            /* set interface up */
-            netif_set_up(ethif->netif);
-#endif
-
-            if (!(ethif->flags & ETHIF_LINK_PHYUP))
-            {
-                netif_set_link_up(ethif->netif);
-            }
-
-            /* enter critical */
-            rt_enter_critical();
-        }
-    }
-
-    /* leave critical */
-    rt_exit_critical();
-    rt_sem_release((rt_sem_t)arg);
-}
-
-/**
- * LwIP system initialization
- */
-int lwip_system_init(void)
-{
-    rt_err_t rc;
-    struct rt_semaphore done_sem;
-
-    /* set default netif to NULL */
-    netif_default = RT_NULL;
-
-    rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO);
-
-    if (rc != RT_EOK)
-    {
-        LWIP_ASSERT("Failed to create semaphore", 0);
-
-        return -1;
-    }
-
-    tcpip_init(tcpip_init_done_callback, (void *)&done_sem);
-
-    /* waiting for initialization done */
-    if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK)
-    {
-        rt_sem_detach(&done_sem);
-
-        return -1;
-    }
-    rt_sem_detach(&done_sem);
-
-    /* set default ip address */
-#if !LWIP_DHCP
-    if (netif_default != RT_NULL)
-    {
-        struct ip_addr ipaddr, netmask, gw;
-
-        IP4_ADDR(&ipaddr, RT_LWIP_IPADDR0, RT_LWIP_IPADDR1, RT_LWIP_IPADDR2, RT_LWIP_IPADDR3);
-        IP4_ADDR(&gw, RT_LWIP_GWADDR0, RT_LWIP_GWADDR1, RT_LWIP_GWADDR2, RT_LWIP_GWADDR3);
-        IP4_ADDR(&netmask, RT_LWIP_MSKADDR0, RT_LWIP_MSKADDR1, RT_LWIP_MSKADDR2, RT_LWIP_MSKADDR3);
-
-        netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw);
-    }
-#endif
-	rt_kprintf("lwIP-%d.%d.%d initialized!\n", LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION);
-
-	return 0;
-}
-INIT_COMPONENT_EXPORT(lwip_system_init);
-
-void sys_init(void)
-{
-    /* nothing on RT-Thread porting */
-}
-
-void lwip_sys_init(void)
-{
-    lwip_system_init();
-}
-
-/*
- * Create a new semaphore
- *
- * @return the operation status, ERR_OK on OK; others on error
- */
-err_t sys_sem_new(sys_sem_t *sem, u8_t count)
-{
-    static unsigned short counter = 0;
-    char tname[RT_NAME_MAX];
-    sys_sem_t tmpsem;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
-    counter ++;
-
-    tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
-    if (tmpsem == RT_NULL)
-        return ERR_MEM;
-    else
-    {
-        *sem = tmpsem;
-
-        return ERR_OK;
-    }
-}
-
-/*
- * Deallocate a semaphore
- */
-void sys_sem_free(sys_sem_t *sem)
-{
-    RT_DEBUG_NOT_IN_INTERRUPT;
-    rt_sem_delete(*sem);
-}
-
-/*
- * Signal a semaphore
- */
-void sys_sem_signal(sys_sem_t *sem)
-{
-    rt_sem_release(*sem);
-}
-
-/*
- * Block the thread while waiting for the semaphore to be signaled
- *
- * @return If the timeout argument is non-zero, it will return the number of milliseconds
- *         spent waiting for the semaphore to be signaled; If the semaphore isn't signaled
- *         within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't 
- *         wait for the semaphore, it will return zero
- */
-u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
-{
-    rt_err_t ret;
-    s32_t t;
-    u32_t tick;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    /* get the begin tick */
-    tick = rt_tick_get();
-    if (timeout == 0)
-        t = RT_WAITING_FOREVER;
-    else
-    {
-        /* convert msecond to os tick */
-        if (timeout < (1000/RT_TICK_PER_SECOND))
-            t = 1;
-        else
-            t = timeout / (1000/RT_TICK_PER_SECOND);
-    }
-
-    ret = rt_sem_take(*sem, t);
-
-    if (ret == -RT_ETIMEOUT)
-        return SYS_ARCH_TIMEOUT;
-    else
-    {
-        if (ret == RT_EOK)
-            ret = 1;
-    }
-
-    /* get elapse msecond */
-    tick = rt_tick_get() - tick;
-
-    /* convert tick to msecond */
-    tick = tick * (1000 / RT_TICK_PER_SECOND);
-    if (tick == 0)
-        tick = 1;
-
-    return tick;
-}
-
-#ifndef sys_sem_valid
-/** Check if a semaphore is valid/allocated:
- *  return 1 for valid, 0 for invalid
- */
-int sys_sem_valid(sys_sem_t *sem)
-{
-    return (int)(*sem);
-}
-#endif
-
-#ifndef sys_sem_set_invalid
-/** Set a semaphore invalid so that sys_sem_valid returns 0
- */
-void sys_sem_set_invalid(sys_sem_t *sem)
-{
-    *sem = RT_NULL;
-}
-#endif
-
-/* ====================== Mutex ====================== */
-
-/** Create a new mutex
- * @param mutex pointer to the mutex to create
- * @return a new mutex
- */
-err_t sys_mutex_new(sys_mutex_t *mutex)
-{
-    static unsigned short counter = 0;
-    char tname[RT_NAME_MAX];
-    sys_mutex_t tmpmutex;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter);
-    counter ++;
-
-    tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_FIFO);
-    if (tmpmutex == RT_NULL)
-        return ERR_MEM;
-    else
-    {
-        *mutex = tmpmutex;
-
-        return ERR_OK;
-    }
-}
-
-/** Lock a mutex
- * @param mutex the mutex to lock
- */
-void sys_mutex_lock(sys_mutex_t *mutex)
-{
-    RT_DEBUG_NOT_IN_INTERRUPT;
-    rt_mutex_take(*mutex, RT_WAITING_FOREVER);
-
-    return;
-}
-
-/** Unlock a mutex
- * @param mutex the mutex to unlock
- */
-void sys_mutex_unlock(sys_mutex_t *mutex)
-{
-    rt_mutex_release(*mutex);
-}
-
-/** Delete a semaphore
- * @param mutex the mutex to delete
- */
-void sys_mutex_free(sys_mutex_t *mutex)
-{
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_mutex_delete(*mutex);
-}
-
-#ifndef sys_mutex_valid
-/** Check if a mutex is valid/allocated:
- *  return 1 for valid, 0 for invalid
- */
-int sys_mutex_valid(sys_mutex_t *mutex)
-{
-    return (int)(*mutex);
-}
-#endif
-
-#ifndef sys_mutex_set_invalid
-/** Set a mutex invalid so that sys_mutex_valid returns 0
- */
-void sys_mutex_set_invalid(sys_mutex_t *mutex)
-{
-    *mutex = RT_NULL;
-}
-#endif
-
-/* ====================== Mailbox ====================== */
-
-/*
- * Create an empty mailbox for maximum "size" elements
- *
- * @return the operation status, ERR_OK on OK; others on error
- */
-err_t sys_mbox_new(sys_mbox_t *mbox, int size)
-{
-    static unsigned short counter = 0;
-    char tname[RT_NAME_MAX];
-    sys_mbox_t tmpmbox;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter);
-    counter ++;
-
-    tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO);
-    if (tmpmbox != RT_NULL)
-    {
-        *mbox = tmpmbox;
-
-        return ERR_OK;
-    }
-
-    return ERR_MEM;
-}
-
-/*
- * Deallocate a mailbox
- */
-void sys_mbox_free(sys_mbox_t *mbox)
-{
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_mb_delete(*mbox);
-
-    return;
-}
-
-/** Post a message to an mbox - may not fail
- * -> blocks if full, only used from tasks not from ISR
- * @param mbox mbox to posts the message
- * @param msg message to post (ATTENTION: can be NULL)
- */
-void sys_mbox_post(sys_mbox_t *mbox, void *msg)
-{
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER);
-
-    return;
-}
-
-/*
- * Try to post the "msg" to the mailbox
- *
- * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full
- */
-err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
-{
-    if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK)
-        return ERR_OK;
-
-    return ERR_MEM;
-}
-
-/** Wait for a new message to arrive in the mbox
- * @param mbox mbox to get a message from
- * @param msg pointer where the message is stored
- * @param timeout maximum time (in milliseconds) to wait for a message
- * @return time (in milliseconds) waited for a message, may be 0 if not waited
-           or SYS_ARCH_TIMEOUT on timeout
- *         The returned time has to be accurate to prevent timer jitter!
- */
-u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
-{
-    rt_err_t ret;
-    s32_t t;
-    u32_t tick;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    /* get the begin tick */
-    tick = rt_tick_get();
-
-    if(timeout == 0)
-        t = RT_WAITING_FOREVER;
-    else
-    {
-        /* convirt msecond to os tick */
-        if (timeout < (1000/RT_TICK_PER_SECOND))
-            t = 1;
-        else
-            t = timeout / (1000/RT_TICK_PER_SECOND);
-    }
-
-    ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, t);
-
-    if(ret == -RT_ETIMEOUT)
-        return SYS_ARCH_TIMEOUT;
-    else
-    {
-        LWIP_ASSERT("rt_mb_recv returned with error!", ret == RT_EOK);
-    }
-
-    /* get elapse msecond */
-    tick = rt_tick_get() - tick;
-
-    /* convert tick to msecond */
-    tick = tick * (1000 / RT_TICK_PER_SECOND);
-    if (tick == 0)
-        tick = 1;
-
-    return tick;
-}
-
-/** Wait for a new message to arrive in the mbox
- * @param mbox mbox to get a message from
- * @param msg pointer where the message is stored
- * @param timeout maximum time (in milliseconds) to wait for a message
- * @return 0 (milliseconds) if a message has been received
- *         or SYS_MBOX_EMPTY if the mailbox is empty
- */
-u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
-{
-    int ret;
-
-    ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, 0);
-
-    if(ret == -RT_ETIMEOUT)
-        return SYS_ARCH_TIMEOUT;
-    else
-    {
-        if (ret == RT_EOK) 
-            ret = 1;
-    }
-
-    return ret;
-}
-
-#ifndef sys_mbox_valid
-/** Check if an mbox is valid/allocated:
- *  return 1 for valid, 0 for invalid
- */
-int sys_mbox_valid(sys_mbox_t *mbox)
-{
-    return (int)(*mbox);
-}
-#endif
-
-#ifndef sys_mbox_set_invalid
-/** Set an mbox invalid so that sys_mbox_valid returns 0
- */
-void sys_mbox_set_invalid(sys_mbox_t *mbox)
-{
-    *mbox = RT_NULL;
-}
-#endif
-
-/* ====================== System ====================== */
-
-/*
- * Start a new thread named "name" with priority "prio" that will begin
- * its execution in the function "thread()". The "arg" argument will be
- * passed as an argument to the thread() function
- */
-sys_thread_t sys_thread_new(const char    *name,
-                            lwip_thread_fn thread,
-                            void          *arg,
-                            int            stacksize,
-                            int            prio)
-{
-    rt_thread_t t;
-
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    /* create thread */
-    t = rt_thread_create(name, thread, arg, stacksize, prio, 20);
-    RT_ASSERT(t != RT_NULL);
-
-    /* startup thread */
-    rt_thread_startup(t);
-
-    return t;
-}
-
-sys_prot_t sys_arch_protect(void)
-{
-    rt_base_t level;
-
-    /* disable interrupt */
-    level = rt_hw_interrupt_disable();
-
-    return level;
-}
-
-void sys_arch_unprotect(sys_prot_t pval)
-{
-    /* enable interrupt */
-    rt_hw_interrupt_enable(pval);
-
-    return;
-}
-
-void sys_arch_assert(const char *file, int line)
-{
-    rt_kprintf("\nAssertion: %d in %s, thread %s\n",
-               line, file, rt_thread_self()->name);
-    RT_ASSERT(0);
-}
-
-u32_t sys_jiffies(void)
-{
-    return rt_tick_get();
-}
-
-u32_t sys_now(void)
-{
-    return rt_tick_get() * (1000 / RT_TICK_PER_SECOND);
-}
-
-RT_WEAK
-void mem_init(void)
-{
-}
-
-void *mem_calloc(mem_size_t count, mem_size_t size)
-{
-    return rt_calloc(count, size);
-}
-
-void *mem_trim(void *mem, mem_size_t size)
-{
-    // return rt_realloc(mem, size);
-    /* not support trim yet */
-    return mem;
-}
-
-void *mem_malloc(mem_size_t size)
-{
-    return rt_malloc(size);
-}
-
-void  mem_free(void *mem)
-{
-    rt_free(mem);
-}
-
-#ifdef RT_LWIP_PPP
-u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size)
-{
-    u32_t len;
-
-    RT_ASSERT(fd != RT_NULL);
-
-    len = rt_device_read((rt_device_t)fd, 0, buf, size);
-    if (len <= 0)
-        return 0;
-
-    return len;
-}
-
-u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size)
-{
-    RT_ASSERT(fd != RT_NULL);
-
-    return rt_device_write((rt_device_t)fd, 0, buf, size);
-}
-
-void sio_read_abort(sio_fd_t fd)
-{
-    rt_kprintf("read_abort\n");
-}
-
-void ppp_trace(int level, const char *format, ...)
-{
-    va_list args;
-    rt_size_t length;
-    static char rt_log_buf[RT_CONSOLEBUF_SIZE];
-
-    va_start(args, format);
-    length = rt_vsprintf(rt_log_buf, format, args);
-    rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length);
-    va_end(args);
-}
-#endif
-
-/*
- * export bsd socket symbol for RT-Thread Application Module
- */
-#if LWIP_SOCKET
-#include <lwip/sockets.h>
-RTM_EXPORT(lwip_accept);
-RTM_EXPORT(lwip_bind);
-RTM_EXPORT(lwip_shutdown);
-RTM_EXPORT(lwip_getpeername);
-RTM_EXPORT(lwip_getsockname);
-RTM_EXPORT(lwip_getsockopt);
-RTM_EXPORT(lwip_setsockopt);
-RTM_EXPORT(lwip_close);
-RTM_EXPORT(lwip_connect);
-RTM_EXPORT(lwip_listen);
-RTM_EXPORT(lwip_recv);
-RTM_EXPORT(lwip_read);
-RTM_EXPORT(lwip_recvfrom);
-RTM_EXPORT(lwip_send);
-RTM_EXPORT(lwip_sendto);
-RTM_EXPORT(lwip_socket);
-RTM_EXPORT(lwip_write);
-RTM_EXPORT(lwip_select);
-RTM_EXPORT(lwip_ioctl);
-RTM_EXPORT(lwip_fcntl);
-
-RTM_EXPORT(lwip_htons);
-RTM_EXPORT(lwip_htonl);
-
-#if LWIP_DNS
-#include <lwip/netdb.h>
-RTM_EXPORT(lwip_gethostbyname);
-RTM_EXPORT(lwip_gethostbyname_r);
-RTM_EXPORT(lwip_freeaddrinfo);
-RTM_EXPORT(lwip_getaddrinfo);
-#endif
-
-#endif
-
-#if LWIP_DHCP
-#include <lwip/dhcp.h>
-RTM_EXPORT(dhcp_start);
-RTM_EXPORT(dhcp_renew);
-RTM_EXPORT(dhcp_stop);
-#endif
-
-#if LWIP_NETIF_API
-#include <lwip/netifapi.h>
-RTM_EXPORT(netifapi_netif_set_addr);
-#endif
-
-#if LWIP_NETIF_LINK_CALLBACK
-RTM_EXPORT(netif_set_link_callback);
-#endif
-
-#if LWIP_NETIF_STATUS_CALLBACK
-RTM_EXPORT(netif_set_status_callback);
-#endif
-
-RTM_EXPORT(netif_find);
-RTM_EXPORT(netif_set_addr);
-RTM_EXPORT(netif_set_ipaddr);
-RTM_EXPORT(netif_set_gw);
-RTM_EXPORT(netif_set_netmask);

+ 0 - 218
components/net/lwip-2.0.0/src/core/def.c

@@ -1,218 +0,0 @@
-/**
- * @file
- * Common functions used throughout the stack.
- *
- * These are reference implementations of the byte swapping functions.
- * Again with the aim of being simple, correct and fully portable.
- * Byte swapping is the second thing you would want to optimize. You will
- * need to port it to your architecture and in your cc.h:
- *
- * \#define lwip_htons(x) your_htons
- * \#define lwip_htonl(x) your_htonl
- *
- * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts.
- * 
- * If you \#define them to htons() and htonl(), you should
- * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
- * defining htonx/ntohx compatibility macros.
-
- * @defgroup sys_nonstandard Non-standard functions
- * @ingroup sys_layer
- * lwIP provides default implementations for non-standard functions.
- * These can be mapped to OS functions to reduce code footprint if desired.
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Simon Goldschmidt
- *
- */
-
-#include "lwip/opt.h"
-#include "lwip/def.h"
-
-#include <string.h>
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#if !defined(lwip_htons)
-/**
- * Convert an u16_t from host- to network byte order.
- *
- * @param n u16_t in host byte order
- * @return n in network byte order
- */
-u16_t
-lwip_htons(u16_t n)
-{
-  return (u16_t)PP_HTONS(n);
-}
-#endif /* lwip_htons */
-
-#if !defined(lwip_htonl)
-/**
- * Convert an u32_t from host- to network byte order.
- *
- * @param n u32_t in host byte order
- * @return n in network byte order
- */
-u32_t
-lwip_htonl(u32_t n)
-{
-  return (u32_t)PP_HTONL(n);
-}
-#endif /* lwip_htonl */
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#ifndef lwip_strnstr
-/**
- * @ingroup sys_nonstandard
- * lwIP default implementation for strnstr() non-standard function.
- * This can be \#defined to strnstr() depending on your platform port.
- */
-char*
-lwip_strnstr(const char* buffer, const char* token, size_t n)
-{
-  const char* p;
-  int tokenlen = (int)strlen(token);
-  if (tokenlen == 0) {
-    return (char *)(size_t)buffer;
-  }
-  for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
-    if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
-      return (char *)(size_t)p;
-    }
-  }
-  return NULL;
-}
-#endif
-
-#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

+ 0 - 1433
components/net/lwip-2.0.0/src/core/dns.c

@@ -1,1433 +0,0 @@
-/**
- * @file
- * DNS - host name to IP address resolver.
- *
- * @defgroup dns DNS
- * @ingroup callbackstyle_api
- *
- * Implements a DNS host name to IP address resolver.
- *
- * The lwIP DNS resolver functions are used to lookup a host name and
- * map it to a numerical IP address. It maintains a list of resolved
- * hostnames that can be queried with the dns_lookup() function.
- * New hostnames can be resolved using the dns_query() function.
- *
- * The lwIP version of the resolver also adds a non-blocking version of
- * gethostbyname() that will work with a raw API application. This function
- * checks for an IP address string first and converts it if it is valid.
- * gethostbyname() then does a dns_lookup() to see if the name is
- * already in the table. If so, the IP is returned. If not, a query is
- * issued and the function returns with a ERR_INPROGRESS status. The app
- * using the dns client must then go into a waiting state.
- *
- * Once a hostname has been resolved (or found to be non-existent),
- * the resolver code calls a specified callback function (which
- * must be implemented by the module that uses the resolver).
- * 
- * All functions must be called from TCPIP thread.
- * 
- * @see @ref netconn_common for thread-safe access.
- */
-
-/*
- * Port to lwIP from uIP
- * by Jim Pettinato April 2007
- *
- * security fixes and more by Simon Goldschmidt
- *
- * uIP version Copyright (c) 2002-2003, Adam Dunkels.
- * 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.
- */
-
-/*-----------------------------------------------------------------------------
- * RFC 1035 - Domain names - implementation and specification
- * RFC 2181 - Clarifications to the DNS Specification
- *----------------------------------------------------------------------------*/
-
-/** @todo: define good default values (rfc compliance) */
-/** @todo: improve answer parsing, more checkings... */
-/** @todo: check RFC1035 - 7.3. Processing responses */
-
-/*-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
-
-#include "lwip/opt.h"
-
-#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/def.h"
-#include "lwip/udp.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
-#include "lwip/dns.h"
-#include "lwip/prot/dns.h"
-
-#include <string.h>
-
-/** Random generator function to create random TXIDs and source ports for queries */
-#ifndef DNS_RAND_TXID
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0)
-#define DNS_RAND_TXID LWIP_RAND
-#else
-static u16_t dns_txid;
-#define DNS_RAND_TXID() (++dns_txid)
-#endif
-#endif
-
-/** Limits the source port to be >= 1024 by default */
-#ifndef DNS_PORT_ALLOWED
-#define DNS_PORT_ALLOWED(port) ((port) >= 1024)
-#endif
-
-/** DNS maximum number of retries when asking for a name, before "timeout". */
-#ifndef DNS_MAX_RETRIES
-#define DNS_MAX_RETRIES           4
-#endif
-
-/** DNS resource record max. TTL (one week as default) */
-#ifndef DNS_MAX_TTL
-#define DNS_MAX_TTL               604800
-#elif DNS_MAX_TTL > 0x7FFFFFFF
-#error DNS_MAX_TTL must be a positive 32-bit value
-#endif
-
-/* The number of parallel requests (i.e. calls to dns_gethostbyname
- * that cannot be answered from the DNS table.
- * This is set to the table size by default.
- */
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
-#ifndef DNS_MAX_REQUESTS
-#define DNS_MAX_REQUESTS          DNS_TABLE_SIZE
-#endif
-#else
-/* In this configuration, both arrays have to have the same size and are used
- * like one entry (used/free) */
-#define DNS_MAX_REQUESTS          DNS_TABLE_SIZE
-#endif
-
-/* The number of UDP source ports used in parallel */
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-#ifndef DNS_MAX_SOURCE_PORTS
-#define DNS_MAX_SOURCE_PORTS      DNS_MAX_REQUESTS
-#endif
-#else
-#ifdef DNS_MAX_SOURCE_PORTS
-#undef DNS_MAX_SOURCE_PORTS
-#endif
-#define DNS_MAX_SOURCE_PORTS      1
-#endif
-
-#if LWIP_IPV4 && LWIP_IPV6
-#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6))
-#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t)))
-#define LWIP_DNS_ADDRTYPE_ARG(x) , x
-#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x
-#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0)
-#else
-#if LWIP_IPV6
-#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1
-#else
-#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0
-#endif
-#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1
-#define LWIP_DNS_ADDRTYPE_ARG(x)
-#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0
-#define LWIP_DNS_SET_ADDRTYPE(x, y)
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-/** DNS query message structure.
-    No packing needed: only used locally on the stack. */
-struct dns_query {
-  /* DNS query record starts with either a domain name or a pointer
-     to a name already present somewhere in the packet. */
-  u16_t type;
-  u16_t cls;
-};
-#define SIZEOF_DNS_QUERY 4
-
-/** DNS answer message structure.
-    No packing needed: only used locally on the stack. */
-struct dns_answer {
-  /* DNS answer record starts with either a domain name or a pointer
-     to a name already present somewhere in the packet. */
-  u16_t type;
-  u16_t cls;
-  u32_t ttl;
-  u16_t len;
-};
-#define SIZEOF_DNS_ANSWER 10
-/* maximum allowed size for the struct due to non-packed */
-#define SIZEOF_DNS_ANSWER_ASSERT 12
-
-/* DNS table entry states */
-typedef enum {
-  DNS_STATE_UNUSED           = 0,
-  DNS_STATE_NEW              = 1,
-  DNS_STATE_ASKING           = 2,
-  DNS_STATE_DONE             = 3
-} dns_state_enum_t;
-
-/** DNS table entry */
-struct dns_table_entry {
-  u32_t ttl;
-  ip_addr_t ipaddr;
-  u16_t txid;
-  u8_t  state;
-  u8_t  server_idx;
-  u8_t  tmr;
-  u8_t  retries;
-  u8_t  seqno;
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-  u8_t pcb_idx;
-#endif
-  char name[DNS_MAX_NAME_LENGTH];
-#if LWIP_IPV4 && LWIP_IPV6
-  u8_t reqaddrtype;
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-};
-
-/** DNS request table entry: used when dns_gehostbyname cannot answer the
- * request from the DNS table */
-struct dns_req_entry {
-  /* pointer to callback on DNS query done */
-  dns_found_callback found;
-  /* argument passed to the callback function */
-  void *arg;
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
-  u8_t dns_table_idx;
-#endif
-#if LWIP_IPV4 && LWIP_IPV6
-  u8_t reqaddrtype;
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-};
-
-#if DNS_LOCAL_HOSTLIST
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/** Local host-list. For hostnames in this list, no
- *  external name resolution is performed */
-static struct local_hostlist_entry *local_hostlist_dynamic;
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
-#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
-#define DNS_LOCAL_HOSTLIST_STORAGE_POST
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
-DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
-  DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
-
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-static void dns_init_local(void);
-#endif /* DNS_LOCAL_HOSTLIST */
-
-
-/* forward declarations */
-static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
-static void dns_check_entries(void);
-static void dns_call_found(u8_t idx, ip_addr_t* addr);
-
-/*-----------------------------------------------------------------------------
- * Globals
- *----------------------------------------------------------------------------*/
-
-/* DNS variables */
-static struct udp_pcb        *dns_pcbs[DNS_MAX_SOURCE_PORTS];
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-static u8_t                   dns_last_pcb_idx;
-#endif
-static u8_t                   dns_seqno;
-static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
-static struct dns_req_entry   dns_requests[DNS_MAX_REQUESTS];
-static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
-
-/**
- * Initialize the resolver: set up the UDP pcb and configure the default server
- * (if DNS_SERVER_ADDRESS is set).
- */
-void
-dns_init(void)
-{
-#ifdef DNS_SERVER_ADDRESS
-  /* initialize default DNS server address */
-  ip_addr_t dnsserver;
-  DNS_SERVER_ADDRESS(&dnsserver);
-  dns_setserver(0, &dnsserver);
-#endif /* DNS_SERVER_ADDRESS */
-
-  LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
-    sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
-  LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER",
-    sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT);
-
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
-
-  /* if dns client not yet initialized... */
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
-  if (dns_pcbs[0] == NULL) {
-    dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY);
-    LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL);
-
-    /* initialize DNS table not needed (initialized to zero since it is a
-     * global variable) */
-    LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
-      DNS_STATE_UNUSED == 0);
-
-    /* initialize DNS client */
-    udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0);
-    udp_recv(dns_pcbs[0], dns_recv, NULL);
-  }
-#endif
-
-#if DNS_LOCAL_HOSTLIST
-  dns_init_local();
-#endif
-}
-
-/**
- * @ingroup dns
- * Initialize one of the DNS servers.
- *
- * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
- * @param dnsserver IP address of the DNS server to set
- */
-void
-dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
-{
-  if (numdns < DNS_MAX_SERVERS) {
-    if (dnsserver != NULL) {
-      dns_servers[numdns] = (*dnsserver);
-    } else {
-      dns_servers[numdns] = *IP4_ADDR_ANY;
-    }
-  }
-}
-
-/**
- * @ingroup dns
- * Obtain one of the currently configured DNS server.
- *
- * @param numdns the index of the DNS server
- * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
- *         server has not been configured.
- */
-const ip_addr_t*
-dns_getserver(u8_t numdns)
-{
-  if (numdns < DNS_MAX_SERVERS) {
-    return &dns_servers[numdns];
-  } else {
-    return IP4_ADDR_ANY;
-  }
-}
-
-/**
- * The DNS resolver client timer - handle retries and timeouts and should
- * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
- */
-void
-dns_tmr(void)
-{
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
-  dns_check_entries();
-}
-
-#if DNS_LOCAL_HOSTLIST
-static void
-dns_init_local(void)
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
-  size_t i;
-  struct local_hostlist_entry *entry;
-  /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
-  struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
-  size_t namelen;
-  for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) {
-    struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
-    LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
-    namelen = strlen(init_entry->name);
-    LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
-    entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
-    LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
-    if (entry != NULL) {
-      char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry);
-      MEMCPY(entry_name, init_entry->name, namelen);
-      entry_name[namelen] = 0;
-      entry->name = entry_name;
-      entry->addr = init_entry->addr;
-      entry->next = local_hostlist_dynamic;
-      local_hostlist_dynamic = entry;
-    }
-  }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
-}
-
-/**
- * @ingroup dns
- * Scans the local host-list for a hostname.
- *
- * @param hostname Hostname to look for in the local host-list
- * @param addr the first IP address for the hostname in the local host-list or
- *         IPADDR_NONE if not found.
- * @return ERR_OK if found, ERR_ARG if not found
- */
-static err_t
-dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-  struct local_hostlist_entry *entry = local_hostlist_dynamic;
-  while (entry != NULL) {
-    if ((lwip_stricmp(entry->name, hostname) == 0) &&
-        LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) {
-      if (addr) {
-        ip_addr_copy(*addr, entry->addr);
-      }
-      return ERR_OK;
-    }
-    entry = entry->next;
-  }
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-  size_t i;
-  for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
-    if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) &&
-        LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) {
-      if (addr) {
-        ip_addr_copy(*addr, local_hostlist_static[i].addr);
-      }
-      return ERR_OK;
-    }
-  }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-  return ERR_ARG;
-}
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/**
- * @ingroup dns
- * Remove all entries from the local host-list for a specific hostname
- * and/or IP address
- *
- * @param hostname hostname for which entries shall be removed from the local
- *                 host-list
- * @param addr address for which entries shall be removed from the local host-list
- * @return the number of removed entries
- */
-int
-dns_local_removehost(const char *hostname, const ip_addr_t *addr)
-{
-  int removed = 0;
-  struct local_hostlist_entry *entry = local_hostlist_dynamic;
-  struct local_hostlist_entry *last_entry = NULL;
-  while (entry != NULL) {
-    if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) &&
-        ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
-      struct local_hostlist_entry *free_entry;
-      if (last_entry != NULL) {
-        last_entry->next = entry->next;
-      } else {
-        local_hostlist_dynamic = entry->next;
-      }
-      free_entry = entry;
-      entry = entry->next;
-      memp_free(MEMP_LOCALHOSTLIST, free_entry);
-      removed++;
-    } else {
-      last_entry = entry;
-      entry = entry->next;
-    }
-  }
-  return removed;
-}
-
-/**
- * @ingroup dns
- * Add a hostname/IP address pair to the local host-list.
- * Duplicates are not checked.
- *
- * @param hostname hostname of the new entry
- * @param addr IP address of the new entry
- * @return ERR_OK if succeeded or ERR_MEM on memory error
- */
-err_t
-dns_local_addhost(const char *hostname, const ip_addr_t *addr)
-{
-  struct local_hostlist_entry *entry;
-  size_t namelen;
-  char* entry_name;
-  LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
-  namelen = strlen(hostname);
-  LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
-  entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
-  if (entry == NULL) {
-    return ERR_MEM;
-  }
-  entry_name = (char*)entry + sizeof(struct local_hostlist_entry);
-  MEMCPY(entry_name, hostname, namelen);
-  entry_name[namelen] = 0;
-  entry->name = entry_name;
-  ip_addr_copy(entry->addr, *addr);
-  entry->next = local_hostlist_dynamic;
-  local_hostlist_dynamic = entry;
-  return ERR_OK;
-}
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
-#endif /* DNS_LOCAL_HOSTLIST */
-
-/**
- * @ingroup dns
- * Look up a hostname in the array of known hostnames.
- *
- * @note This function only looks in the internal array of known
- * hostnames, it does not send out a query for the hostname if none
- * was found. The function dns_enqueue() can be used to send a query
- * for a hostname.
- *
- * @param name the hostname to look up
- * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to
- *         better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
- *         was not found in the cached dns_table.
- * @return ERR_OK if found, ERR_ARG if not found
- */
-static err_t
-dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
-{
-  u8_t i;
-#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
-#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
-#if DNS_LOCAL_HOSTLIST
-  if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
-    return ERR_OK;
-  }
-#endif /* DNS_LOCAL_HOSTLIST */
-#ifdef DNS_LOOKUP_LOCAL_EXTERN
-  if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) {
-    return ERR_OK;
-  }
-#endif /* DNS_LOOKUP_LOCAL_EXTERN */
-
-  /* Walk through name list, return entry if found. If not, return NULL. */
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    if ((dns_table[i].state == DNS_STATE_DONE) &&
-        (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) &&
-        LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) {
-      LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
-      ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
-      LWIP_DEBUGF(DNS_DEBUG, ("\n"));
-      if (addr) {
-        ip_addr_copy(*addr, dns_table[i].ipaddr);
-      }
-      return ERR_OK;
-    }
-  }
-
-  return ERR_ARG;
-}
-
-/**
- * Compare the "dotted" name "query" with the encoded name "response"
- * to make sure an answer from the DNS server matches the current dns_table
- * entry (otherwise, answers might arrive late for hostname not on the list
- * any more).
- *
- * @param query hostname (not encoded) from the dns_table
- * @param p pbuf containing the encoded hostname in the DNS response
- * @param start_offset offset into p where the name starts
- * @return 0xFFFF: names differ, other: names equal -> offset behind name
- */
-static u16_t
-dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset)
-{
-  int n;
-  u16_t response_offset = start_offset;
-
-  do {
-    n = pbuf_try_get_at(p, response_offset++);
-    if (n < 0) {
-      return 0xFFFF;
-    }
-    /** @see RFC 1035 - 4.1.4. Message compression */
-    if ((n & 0xc0) == 0xc0) {
-      /* Compressed name: cannot be equal since we don't send them */
-      return 0xFFFF;
-    } else {
-      /* Not compressed name */
-      while (n > 0) {
-        int c = pbuf_try_get_at(p, response_offset);
-        if (c < 0) {
-          return 0xFFFF;
-        }
-        if ((*query) != (u8_t)c) {
-          return 0xFFFF;
-        }
-        ++response_offset;
-        ++query;
-        --n;
-      }
-      ++query;
-    }
-    n = pbuf_try_get_at(p, response_offset);
-    if (n < 0) {
-      return 0xFFFF;
-    }
-  } while (n != 0);
-
-  return response_offset + 1;
-}
-
-/**
- * Walk through a compact encoded DNS name and return the end of the name.
- *
- * @param p pbuf containing the name
- * @param query_idx start index into p pointing to encoded DNS name in the DNS server response
- * @return index to end of the name
- */
-static u16_t
-dns_skip_name(struct pbuf* p, u16_t query_idx)
-{
-  int n;
-  u16_t offset = query_idx;
-
-  do {
-    n = pbuf_try_get_at(p, offset++);
-    if (n < 0) {
-      return 0xFFFF;
-    }
-    /** @see RFC 1035 - 4.1.4. Message compression */
-    if ((n & 0xc0) == 0xc0) {
-      /* Compressed name: since we only want to skip it (not check it), stop here */
-      break;
-    } else {
-      /* Not compressed name */
-      if (offset + n >= p->tot_len) {
-        return 0xFFFF;
-      }
-      offset = (u16_t)(offset + n);
-    }
-    n = pbuf_try_get_at(p, offset);
-    if (n < 0) {
-      return 0xFFFF;
-    }
-  } while (n != 0);
-
-  return offset + 1;
-}
-
-/**
- * Send a DNS query packet.
- *
- * @param idx the DNS table entry index for which to send a request
- * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
- */
-static err_t
-dns_send(u8_t idx)
-{
-  err_t err;
-  struct dns_hdr hdr;
-  struct dns_query qry;
-  struct pbuf *p;
-  u16_t query_idx, copy_len;
-  const char *hostname, *hostname_part;
-  u8_t n;
-  u8_t pcb_idx;
-  struct dns_table_entry* entry = &dns_table[idx];
-
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
-              (u16_t)(entry->server_idx), entry->name));
-  LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
-  if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
-    /* DNS server not valid anymore, e.g. PPP netif has been shut down */
-    /* call specified callback function if provided */
-    dns_call_found(idx, NULL);
-    /* flush this entry */
-    entry->state = DNS_STATE_UNUSED;
-    return ERR_OK;
-  }
-
-  /* if here, we have either a new query or a retry on a previous query to process */
-  p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
-                 SIZEOF_DNS_QUERY), PBUF_RAM);
-  if (p != NULL) {
-    /* fill dns header */
-    memset(&hdr, 0, SIZEOF_DNS_HDR);
-    hdr.id = lwip_htons(entry->txid);
-    hdr.flags1 = DNS_FLAG1_RD;
-    hdr.numquestions = PP_HTONS(1);
-    pbuf_take(p, &hdr, SIZEOF_DNS_HDR);
-    hostname = entry->name;
-    --hostname;
-
-    /* convert hostname into suitable query format. */
-    query_idx = SIZEOF_DNS_HDR;
-    do {
-      ++hostname;
-      hostname_part = hostname;
-      for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) {
-        ++n;
-      }
-      copy_len = (u16_t)(hostname - hostname_part);
-      pbuf_put_at(p, query_idx, n);
-      pbuf_take_at(p, hostname_part, copy_len, query_idx + 1);
-      query_idx += n + 1;
-    } while (*hostname != 0);
-    pbuf_put_at(p, query_idx, 0);
-    query_idx++;
-
-    /* fill dns query */
-    if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) {
-      qry.type = PP_HTONS(DNS_RRTYPE_AAAA);
-    } else {
-      qry.type = PP_HTONS(DNS_RRTYPE_A);
-    }
-    qry.cls = PP_HTONS(DNS_RRCLASS_IN);
-    pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx);
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-    pcb_idx = entry->pcb_idx;
-#else
-    pcb_idx = 0;
-#endif
-    /* send dns packet */
-    LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
-      entry->txid, entry->name, entry->server_idx));
-    err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT);
-
-    /* free pbuf */
-    pbuf_free(p);
-  } else {
-    err = ERR_MEM;
-  }
-
-  return err;
-}
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-static struct udp_pcb*
-dns_alloc_random_port(void)
-{
-  err_t err;
-  struct udp_pcb* ret;
-
-  ret = udp_new_ip_type(IPADDR_TYPE_ANY);
-  if (ret == NULL) {
-    /* out of memory, have to reuse an existing pcb */
-    return NULL;
-  }
-  do {
-    u16_t port = (u16_t)DNS_RAND_TXID();
-    if (!DNS_PORT_ALLOWED(port)) {
-      /* this port is not allowed, try again */
-      err = ERR_USE;
-      continue;
-    }
-    err = udp_bind(ret, IP_ANY_TYPE, port);
-  } while (err == ERR_USE);
-  if (err != ERR_OK) {
-    udp_remove(ret);
-    return NULL;
-  }
-  udp_recv(ret, dns_recv, NULL);
-  return ret;
-}
-
-/**
- * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used
- * for sending a request
- *
- * @return an index into dns_pcbs
- */
-static u8_t
-dns_alloc_pcb(void)
-{
-  u8_t i;
-  u8_t idx;
-
-  for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) {
-    if (dns_pcbs[i] == NULL) {
-      break;
-    }
-  }
-  if (i < DNS_MAX_SOURCE_PORTS) {
-    dns_pcbs[i] = dns_alloc_random_port();
-    if (dns_pcbs[i] != NULL) {
-      /* succeeded */
-      dns_last_pcb_idx = i;
-      return i;
-    }
-  }
-  /* if we come here, creating a new UDP pcb failed, so we have to use
-     an already existing one */
-  for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) {
-    if (idx >= DNS_MAX_SOURCE_PORTS) {
-      idx = 0;
-    }
-    if (dns_pcbs[idx] != NULL) {
-      dns_last_pcb_idx = idx;
-      return idx;
-    }
-  }
-  return DNS_MAX_SOURCE_PORTS;
-}
-#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */
-
-/**
- * dns_call_found() - call the found callback and check if there are duplicate
- * entries for the given hostname. If there are any, their found callback will
- * be called and they will be removed.
- *
- * @param idx dns table index of the entry that is resolved or removed
- * @param addr IP address for the hostname (or NULL on error or memory shortage)
- */
-static void
-dns_call_found(u8_t idx, ip_addr_t* addr)
-{
-#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0)
-  u8_t i;
-#endif
-
-#if LWIP_IPV4 && LWIP_IPV6
-  if (addr != NULL) {
-    /* check that address type matches the request and adapt the table entry */
-    if (IP_IS_V6_VAL(*addr)) {
-      LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
-      dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
-    } else {
-      LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
-      dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
-    }
-  }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
-  for (i = 0; i < DNS_MAX_REQUESTS; i++) {
-    if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) {
-      (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg);
-      /* flush this entry */
-      dns_requests[i].found = NULL;
-    }
-  }
-#else
-  if (dns_requests[idx].found) {
-    (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg);
-  }
-  dns_requests[idx].found = NULL;
-#endif
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-  /* close the pcb used unless other request are using it */
-  for (i = 0; i < DNS_MAX_REQUESTS; i++) {
-    if (i == idx) {
-      continue; /* only check other requests */
-    }
-    if (dns_table[i].state == DNS_STATE_ASKING) {
-      if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) {
-        /* another request is still using the same pcb */
-        dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
-        break;
-      }
-    }
-  }
-  if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) {
-    /* if we come here, the pcb is not used any more and can be removed */
-    udp_remove(dns_pcbs[dns_table[idx].pcb_idx]);
-    dns_pcbs[dns_table[idx].pcb_idx] = NULL;
-    dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
-  }
-#endif
-}
-
-/* Create a query transmission ID that is unique for all outstanding queries */
-static u16_t
-dns_create_txid(void)
-{
-  u16_t txid;
-  u8_t i;
-
-again:
-  txid = (u16_t)DNS_RAND_TXID();
-
-  /* check whether the ID is unique */
-  for (i = 0; i < DNS_TABLE_SIZE; i++) {
-    if ((dns_table[i].state == DNS_STATE_ASKING) &&
-        (dns_table[i].txid == txid)) {
-      /* ID already used by another pending query */
-      goto again;
-    }
-  }
-
-  return txid;
-}
-
-/**
- * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query.
- * Check an entry in the dns_table:
- * - send out query for new entries
- * - retry old pending entries on timeout (also with different servers)
- * - remove completed entries from the table if their TTL has expired
- *
- * @param i index of the dns_table entry to check
- */
-static void
-dns_check_entry(u8_t i)
-{
-  err_t err;
-  struct dns_table_entry *entry = &dns_table[i];
-
-  LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
-
-  switch (entry->state) {
-    case DNS_STATE_NEW:
-      /* initialize new entry */
-      entry->txid = dns_create_txid();
-      entry->state = DNS_STATE_ASKING;
-      entry->server_idx = 0;
-      entry->tmr = 1;
-      entry->retries = 0;
-
-      /* send DNS packet for this entry */
-      err = dns_send(i);
-      if (err != ERR_OK) {
-        LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
-                    ("dns_send returned error: %s\n", lwip_strerr(err)));
-      }
-      break;
-    case DNS_STATE_ASKING:
-      if (--entry->tmr == 0) {
-        if (++entry->retries == DNS_MAX_RETRIES) {
-          if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
-            /* change of server */
-            entry->server_idx++;
-            entry->tmr = 1;
-            entry->retries = 0;
-          } else {
-            LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name));
-            /* call specified callback function if provided */
-            dns_call_found(i, NULL);
-            /* flush this entry */
-            entry->state = DNS_STATE_UNUSED;
-            break;
-          }
-        } else {
-          /* wait longer for the next retry */
-          entry->tmr = entry->retries;
-        }
-
-        /* send DNS packet for this entry */
-        err = dns_send(i);
-        if (err != ERR_OK) {
-          LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
-                      ("dns_send returned error: %s\n", lwip_strerr(err)));
-        }
-      }
-      break;
-    case DNS_STATE_DONE:
-      /* if the time to live is nul */
-      if ((entry->ttl == 0) || (--entry->ttl == 0)) {
-        LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name));
-        /* flush this entry, there cannot be any related pending entries in this state */
-        entry->state = DNS_STATE_UNUSED;
-      }
-      break;
-    case DNS_STATE_UNUSED:
-      /* nothing to do */
-      break;
-    default:
-      LWIP_ASSERT("unknown dns_table entry state:", 0);
-      break;
-  }
-}
-
-/**
- * Call dns_check_entry for each entry in dns_table - check all entries.
- */
-static void
-dns_check_entries(void)
-{
-  u8_t i;
-
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    dns_check_entry(i);
-  }
-}
-
-/**
- * Save TTL and call dns_call_found for correct response.
- */
-static void
-dns_correct_response(u8_t idx, u32_t ttl)
-{
-  struct dns_table_entry *entry = &dns_table[idx];
-
-  entry->state = DNS_STATE_DONE;
-
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
-  ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
-  LWIP_DEBUGF(DNS_DEBUG, ("\n"));
-
-  /* read the answer resource record's TTL, and maximize it if needed */
-  entry->ttl = ttl;
-  if (entry->ttl > DNS_MAX_TTL) {
-    entry->ttl = DNS_MAX_TTL;
-  }
-  dns_call_found(idx, &entry->ipaddr);
-
-  if (entry->ttl == 0) {
-    /* RFC 883, page 29: "Zero values are
-       interpreted to mean that the RR can only be used for the
-       transaction in progress, and should not be cached."
-       -> flush this entry now */
-    /* entry reused during callback? */
-    if (entry->state == DNS_STATE_DONE) {
-      entry->state = DNS_STATE_UNUSED;
-    }
-  }
-}
-/**
- * Receive input function for DNS response packets arriving for the dns UDP pcb.
- */
-static void
-dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
-{
-  u8_t i;
-  u16_t txid;
-  u16_t res_idx;
-  struct dns_hdr hdr;
-  struct dns_answer ans;
-  struct dns_query qry;
-  u16_t nquestions, nanswers;
-
-  LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_UNUSED_ARG(port);
-
-  /* is the dns message big enough ? */
-  if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) {
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
-    /* free pbuf and return */
-    goto memerr;
-  }
-
-  /* copy dns payload inside static buffer for processing */
-  if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) {
-    /* Match the ID in the DNS header with the name table. */
-    txid = lwip_htons(hdr.id);
-    for (i = 0; i < DNS_TABLE_SIZE; i++) {
-      const struct dns_table_entry *entry = &dns_table[i];
-      if ((entry->state == DNS_STATE_ASKING) &&
-          (entry->txid == txid)) {
-
-        /* We only care about the question(s) and the answers. The authrr
-           and the extrarr are simply discarded. */
-        nquestions = lwip_htons(hdr.numquestions);
-        nanswers   = lwip_htons(hdr.numanswers);
-
-        /* Check for correct response. */
-        if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name));
-          goto memerr; /* ignore this packet */
-        }
-        if (nquestions != 1) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
-          goto memerr; /* ignore this packet */
-        }
-
-        /* Check whether response comes from the same network address to which the
-           question was sent. (RFC 5452) */
-        if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
-          goto memerr; /* ignore this packet */
-        }
-
-        /* Check if the name in the "question" part match with the name in the entry and
-           skip it if equal. */
-        res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR);
-        if (res_idx == 0xFFFF) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
-          goto memerr; /* ignore this packet */
-        }
-
-        /* check if "question" part matches the request */
-        if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) {
-          goto memerr; /* ignore this packet */
-        }
-        if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) ||
-          (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) ||
-          (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
-          goto memerr; /* ignore this packet */
-        }
-        /* skip the rest of the "question" part */
-        res_idx += SIZEOF_DNS_QUERY;
-
-        /* Check for error. If so, call callback to inform. */
-        if (hdr.flags2 & DNS_FLAG2_ERR_MASK) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name));
-        } else {
-          while ((nanswers > 0) && (res_idx < p->tot_len)) {
-            /* skip answer resource record's host name */
-            res_idx = dns_skip_name(p, res_idx);
-            if (res_idx == 0xFFFF) {
-              goto memerr; /* ignore this packet */
-            }
-
-            /* Check for IP address type and Internet class. Others are discarded. */
-            if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) {
-              goto memerr; /* ignore this packet */
-            }
-            res_idx += SIZEOF_DNS_ANSWER;
-
-            if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) {
-#if LWIP_IPV4
-              if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) {
-#if LWIP_IPV4 && LWIP_IPV6
-                if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-                {
-                  ip4_addr_t ip4addr;
-                  /* read the IP address after answer resource record's header */
-                  if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) {
-                    goto memerr; /* ignore this packet */
-                  }
-                  ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr);
-                  pbuf_free(p);
-                  /* handle correct response */
-                  dns_correct_response(i, lwip_ntohl(ans.ttl));
-                  return;
-                }
-              }
-#endif /* LWIP_IPV4 */
-#if LWIP_IPV6
-              if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) {
-#if LWIP_IPV4 && LWIP_IPV6
-                if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-                {
-                  ip6_addr_t ip6addr;
-                  /* read the IP address after answer resource record's header */
-                  if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) {
-                    goto memerr; /* ignore this packet */
-                  }
-                  ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr);
-                  pbuf_free(p);
-                  /* handle correct response */
-                  dns_correct_response(i, lwip_ntohl(ans.ttl));
-                  return;
-                }
-              }
-#endif /* LWIP_IPV6 */
-            }
-            /* skip this answer */
-            if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) {
-              goto memerr; /* ignore this packet */
-            }
-            res_idx += lwip_htons(ans.len);
-            --nanswers;
-          }
-#if LWIP_IPV4 && LWIP_IPV6
-          if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) ||
-              (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
-            if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
-              /* IPv4 failed, try IPv6 */
-              dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
-            } else {
-              /* IPv6 failed, try IPv4 */
-              dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
-            }
-            pbuf_free(p);
-            dns_table[i].state = DNS_STATE_NEW;
-            dns_check_entry(i);
-            return;
-          }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name));
-        }
-        /* call callback to indicate error, clean up memory and return */
-        pbuf_free(p);
-        dns_call_found(i, NULL);
-        dns_table[i].state = DNS_STATE_UNUSED;
-        return;
-      }
-    }
-  }
-
-memerr:
-  /* deallocate memory and return */
-  pbuf_free(p);
-  return;
-}
-
-/**
- * Queues a new hostname to resolve and sends out a DNS query for that hostname
- *
- * @param name the hostname that is to be queried
- * @param hostnamelen length of the hostname
- * @param found a callback function to be called on success, failure or timeout
- * @param callback_arg argument to pass to the callback function
- * @return err_t return code.
- */
-static err_t
-dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
-            void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
-{
-  u8_t i;
-  u8_t lseq, lseqi;
-  struct dns_table_entry *entry = NULL;
-  size_t namelen;
-  struct dns_req_entry* req;
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
-  u8_t r;
-  /* check for duplicate entries */
-  for (i = 0; i < DNS_TABLE_SIZE; i++) {
-    if ((dns_table[i].state == DNS_STATE_ASKING) &&
-        (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) {
-#if LWIP_IPV4 && LWIP_IPV6
-      if (dns_table[i].reqaddrtype != dns_addrtype) {
-        /* requested address types don't match
-           this can lead to 2 concurrent requests, but mixing the address types
-           for the same host should not be that common */
-        continue;
-      }
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-      /* this is a duplicate entry, find a free request entry */
-      for (r = 0; r < DNS_MAX_REQUESTS; r++) {
-        if (dns_requests[r].found == 0) {
-          dns_requests[r].found = found;
-          dns_requests[r].arg = callback_arg;
-          dns_requests[r].dns_table_idx = i;
-          LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype);
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name));
-          return ERR_INPROGRESS;
-        }
-      }
-    }
-  }
-  /* no duplicate entries found */
-#endif
-
-  /* search an unused entry, or the oldest one */
-  lseq = 0;
-  lseqi = DNS_TABLE_SIZE;
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    entry = &dns_table[i];
-    /* is it an unused entry ? */
-    if (entry->state == DNS_STATE_UNUSED) {
-      break;
-    }
-    /* check if this is the oldest completed entry */
-    if (entry->state == DNS_STATE_DONE) {
-      if ((u8_t)(dns_seqno - entry->seqno) > lseq) {
-        lseq = dns_seqno - entry->seqno;
-        lseqi = i;
-      }
-    }
-  }
-
-  /* if we don't have found an unused entry, use the oldest completed one */
-  if (i == DNS_TABLE_SIZE) {
-    if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
-      /* no entry can be used now, table is full */
-      LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
-      return ERR_MEM;
-    } else {
-      /* use the oldest completed one */
-      i = lseqi;
-      entry = &dns_table[i];
-    }
-  }
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
-  /* find a free request entry */
-  req = NULL;
-  for (r = 0; r < DNS_MAX_REQUESTS; r++) {
-    if (dns_requests[r].found == NULL) {
-      req = &dns_requests[r];
-      break;
-    }
-  }
-  if (req == NULL) {
-    /* no request entry can be used now, table is full */
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name));
-    return ERR_MEM;
-  }
-  req->dns_table_idx = i;
-#else
-  /* in this configuration, the entry index is the same as the request index */
-  req = &dns_requests[i];
-#endif
-
-  /* use this entry */
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
-
-  /* fill the entry */
-  entry->state = DNS_STATE_NEW;
-  entry->seqno = dns_seqno;
-  LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype);
-  LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype);
-  req->found = found;
-  req->arg   = callback_arg;
-  namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1);
-  MEMCPY(entry->name, name, namelen);
-  entry->name[namelen] = 0;
-
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
-  entry->pcb_idx = dns_alloc_pcb();
-  if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) {
-    /* failed to get a UDP pcb */
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name));
-    entry->state = DNS_STATE_UNUSED;
-    req->found = NULL;
-    return ERR_MEM;
-  }
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
-#endif
-
-  dns_seqno++;
-
-  /* force to send query without waiting timer */
-  dns_check_entry(i);
-
-  /* dns query is enqueued */
-  return ERR_INPROGRESS;
-}
-
-/**
- * @ingroup dns
- * Resolve a hostname (string) into an IP address.
- * NON-BLOCKING callback version for use with raw API!!!
- *
- * Returns immediately with one of err_t return codes:
- * - ERR_OK if hostname is a valid IP address string or the host
- *   name is already in the local names table.
- * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
- *   for resolution if no errors are present.
- * - ERR_ARG: dns client not initialized or invalid hostname
- *
- * @param hostname the hostname that is to be queried
- * @param addr pointer to a ip_addr_t where to store the address if it is already
- *             cached in the dns_table (only valid if ERR_OK is returned!)
- * @param found a callback function to be called on success, failure or timeout (only if
- *              ERR_INPROGRESS is returned!)
- * @param callback_arg argument to pass to the callback function
- * @return a err_t return code.
- */
-err_t
-dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
-                  void *callback_arg)
-{
-  return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT);
-}
-
-/**
- * @ingroup dns
- * Like dns_gethostbyname, but returned address type can be controlled:
- * @param hostname the hostname that is to be queried
- * @param addr pointer to a ip_addr_t where to store the address if it is already
- *             cached in the dns_table (only valid if ERR_OK is returned!)
- * @param found a callback function to be called on success, failure or timeout (only if
- *              ERR_INPROGRESS is returned!)
- * @param callback_arg argument to pass to the callback function
- * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
- *                      - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
- *                      - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
- *                      - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
- */
-err_t
-dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,
-                           void *callback_arg, u8_t dns_addrtype)
-{
-  size_t hostnamelen;
-  /* not initialized or no valid server yet, or invalid addr pointer
-   * or invalid hostname or invalid hostname length */
-  if ((addr == NULL) ||
-      (!hostname) || (!hostname[0])) {
-    return ERR_ARG;
-  }
-#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
-  if (dns_pcbs[0] == NULL) {
-    return ERR_ARG;
-  }
-#endif
-  hostnamelen = strlen(hostname);
-  if (hostnamelen >= DNS_MAX_NAME_LENGTH) {
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve"));
-    return ERR_ARG;
-  }
-
-
-#if LWIP_HAVE_LOOPIF
-  if (strcmp(hostname, "localhost") == 0) {
-    ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr);
-    return ERR_OK;
-  }
-#endif /* LWIP_HAVE_LOOPIF */
-
-  /* host name already in octet notation? set ip addr and return ERR_OK */
-  if (ipaddr_aton(hostname, addr)) {
-#if LWIP_IPV4 && LWIP_IPV6
-    if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) ||
-        (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6)))
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-    {
-      return ERR_OK;
-    }
-  }
-  /* already have this address cached? */
-  if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
-    return ERR_OK;
-  }
-#if LWIP_IPV4 && LWIP_IPV6
-  if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
-    /* fallback to 2nd IP type and try again to lookup */
-    u8_t fallback;
-    if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
-      fallback = LWIP_DNS_ADDRTYPE_IPV6;
-    } else {
-      fallback = LWIP_DNS_ADDRTYPE_IPV4;
-    }
-    if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) {
-      return ERR_OK;
-    }
-  }
-#else /* LWIP_IPV4 && LWIP_IPV6 */
-  LWIP_UNUSED_ARG(dns_addrtype);
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-  /* prevent calling found callback if no server is set, return error instead */
-  if (ip_addr_isany_val(dns_servers[0])) {
-    return ERR_VAL;
-  }
-
-  /* queue query with specified callback */
-  return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
-}
-
-#endif /* LWIP_DNS */

+ 0 - 610
components/net/lwip-2.0.0/src/core/inet_chksum.c

@@ -1,610 +0,0 @@
-/**
- * @file
- * Incluse internet checksum functions.\n
- *
- * These are some reference implementations of the checksum algorithm, with the
- * aim of being simple, correct and fully portable. Checksumming is the
- * first thing you would want to optimize for your platform. If you create
- * your own version, link it in and in your cc.h put:
- *
- * \#define LWIP_CHKSUM your_checksum_routine
- * 
- * Or you can select from the implementations below by defining
- * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#include "lwip/inet_chksum.h"
-#include "lwip/def.h"
-#include "lwip/ip_addr.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#ifndef LWIP_CHKSUM
-# define LWIP_CHKSUM lwip_standard_chksum
-# ifndef LWIP_CHKSUM_ALGORITHM
-#  define LWIP_CHKSUM_ALGORITHM 2
-# endif
-u16_t lwip_standard_chksum(const void *dataptr, int len);
-#endif
-/* If none set: */
-#ifndef LWIP_CHKSUM_ALGORITHM
-# define LWIP_CHKSUM_ALGORITHM 0
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
-/**
- * lwip checksum
- *
- * @param dataptr points to start of data to be summed at any boundary
- * @param len length of data to be summed
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- *
- * @note accumulator size limits summable length to 64k
- * @note host endianess is irrelevant (p3 RFC1071)
- */
-u16_t
-lwip_standard_chksum(const void *dataptr, int len)
-{
-  u32_t acc;
-  u16_t src;
-  const u8_t *octetptr;
-
-  acc = 0;
-  /* dataptr may be at odd or even addresses */
-  octetptr = (const u8_t*)dataptr;
-  while (len > 1) {
-    /* declare first octet as most significant
-       thus assume network order, ignoring host order */
-    src = (*octetptr) << 8;
-    octetptr++;
-    /* declare second octet as least significant */
-    src |= (*octetptr);
-    octetptr++;
-    acc += src;
-    len -= 2;
-  }
-  if (len > 0) {
-    /* accumulate remaining octet */
-    src = (*octetptr) << 8;
-    acc += src;
-  }
-  /* add deferred carry bits */
-  acc = (acc >> 16) + (acc & 0x0000ffffUL);
-  if ((acc & 0xffff0000UL) != 0) {
-    acc = (acc >> 16) + (acc & 0x0000ffffUL);
-  }
-  /* This maybe a little confusing: reorder sum using lwip_htons()
-     instead of lwip_ntohs() since it has a little less call overhead.
-     The caller must invert bits for Internet sum ! */
-  return lwip_htons((u16_t)acc);
-}
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */
-/*
- * Curt McDowell
- * Broadcom Corp.
- * csm@broadcom.com
- *
- * IP checksum two bytes at a time with support for
- * unaligned buffer.
- * Works for len up to and including 0x20000.
- * by Curt McDowell, Broadcom Corp. 12/08/2005
- *
- * @param dataptr points to start of data to be summed at any boundary
- * @param len length of data to be summed
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- */
-u16_t
-lwip_standard_chksum(const void *dataptr, int len)
-{
-  const u8_t *pb = (const u8_t *)dataptr;
-  const u16_t *ps;
-  u16_t t = 0;
-  u32_t sum = 0;
-  int odd = ((mem_ptr_t)pb & 1);
-
-  /* Get aligned to u16_t */
-  if (odd && len > 0) {
-    ((u8_t *)&t)[1] = *pb++;
-    len--;
-  }
-
-  /* Add the bulk of the data */
-  ps = (const u16_t *)(const void *)pb;
-  while (len > 1) {
-    sum += *ps++;
-    len -= 2;
-  }
-
-  /* Consume left-over byte, if any */
-  if (len > 0) {
-    ((u8_t *)&t)[0] = *(const u8_t *)ps;
-  }
-
-  /* Add end bytes */
-  sum += t;
-
-  /* Fold 32-bit sum to 16 bits
-     calling this twice is probably faster than if statements... */
-  sum = FOLD_U32T(sum);
-  sum = FOLD_U32T(sum);
-
-  /* Swap if alignment was odd */
-  if (odd) {
-    sum = SWAP_BYTES_IN_WORD(sum);
-  }
-
-  return (u16_t)sum;
-}
-#endif
-
-#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */
-/**
- * An optimized checksum routine. Basically, it uses loop-unrolling on
- * the checksum loop, treating the head and tail bytes specially, whereas
- * the inner loop acts on 8 bytes at a time.
- *
- * @arg start of buffer to be checksummed. May be an odd byte address.
- * @len number of bytes in the buffer to be checksummed.
- * @return host order (!) lwip checksum (non-inverted Internet sum)
- *
- * by Curt McDowell, Broadcom Corp. December 8th, 2005
- */
-u16_t
-lwip_standard_chksum(const void *dataptr, int len)
-{
-  const u8_t *pb = (const u8_t *)dataptr;
-  const u16_t *ps;
-  u16_t t = 0;
-  const u32_t *pl;
-  u32_t sum = 0, tmp;
-  /* starts at odd byte address? */
-  int odd = ((mem_ptr_t)pb & 1);
-
-  if (odd && len > 0) {
-    ((u8_t *)&t)[1] = *pb++;
-    len--;
-  }
-
-  ps = (const u16_t *)(const void*)pb;
-
-  if (((mem_ptr_t)ps & 3) && len > 1) {
-    sum += *ps++;
-    len -= 2;
-  }
-
-  pl = (const u32_t *)(const void*)ps;
-
-  while (len > 7)  {
-    tmp = sum + *pl++;          /* ping */
-    if (tmp < sum) {
-      tmp++;                    /* add back carry */
-    }
-
-    sum = tmp + *pl++;          /* pong */
-    if (sum < tmp) {
-      sum++;                    /* add back carry */
-    }
-
-    len -= 8;
-  }
-
-  /* make room in upper bits */
-  sum = FOLD_U32T(sum);
-
-  ps = (const u16_t *)pl;
-
-  /* 16-bit aligned word remaining? */
-  while (len > 1) {
-    sum += *ps++;
-    len -= 2;
-  }
-
-  /* dangling tail byte remaining? */
-  if (len > 0) {                /* include odd byte */
-    ((u8_t *)&t)[0] = *(const u8_t *)ps;
-  }
-
-  sum += t;                     /* add end bytes */
-
-  /* Fold 32-bit sum to 16 bits
-     calling this twice is probably faster than if statements... */
-  sum = FOLD_U32T(sum);
-  sum = FOLD_U32T(sum);
-
-  if (odd) {
-    sum = SWAP_BYTES_IN_WORD(sum);
-  }
-
-  return (u16_t)sum;
-}
-#endif
-
-/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
-static u16_t
-inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
-{
-  struct pbuf *q;
-  u8_t swapped = 0;
-
-  /* iterate through all pbuf in chain */
-  for (q = p; q != NULL; q = q->next) {
-    LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
-      (void *)q, (void *)q->next));
-    acc += LWIP_CHKSUM(q->payload, q->len);
-    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
-    /* just executing this next line is probably faster that the if statement needed
-       to check whether we really need to execute it, and does no harm */
-    acc = FOLD_U32T(acc);
-    if (q->len % 2 != 0) {
-      swapped = 1 - swapped;
-      acc = SWAP_BYTES_IN_WORD(acc);
-    }
-    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
-  }
-
-  if (swapped) {
-    acc = SWAP_BYTES_IN_WORD(acc);
-  }
-
-  acc += (u32_t)lwip_htons((u16_t)proto);
-  acc += (u32_t)lwip_htons(proto_len);
-
-  /* Fold 32-bit sum to 16 bits
-     calling this twice is probably faster than if statements... */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-  LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
-  return (u16_t)~(acc & 0xffffUL);
-}
-
-#if LWIP_IPV4
-/* inet_chksum_pseudo:
- *
- * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
- * IP addresses are expected to be in network byte order.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param src source ip address (used for checksum of pseudo header)
- * @param dst destination ip address (used for checksum of pseudo header)
- * @param proto ip protocol (used for checksum of pseudo header)
- * @param proto_len length of the ip data part (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
-       const ip4_addr_t *src, const ip4_addr_t *dest)
-{
-  u32_t acc;
-  u32_t addr;
-
-  addr = ip4_addr_get_u32(src);
-  acc = (addr & 0xffffUL);
-  acc += ((addr >> 16) & 0xffffUL);
-  addr = ip4_addr_get_u32(dest);
-  acc += (addr & 0xffffUL);
-  acc += ((addr >> 16) & 0xffffUL);
-  /* fold down to 16 bits */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-
-  return inet_cksum_pseudo_base(p, proto, proto_len, acc);
-}
-#endif /* LWIP_IPV4 */
-
-#if LWIP_IPV6
-/**
- * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
- * IPv6 addresses are expected to be in network byte order.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param proto ipv6 protocol/next header (used for checksum of pseudo header)
- * @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
- * @param src source ipv6 address (used for checksum of pseudo header)
- * @param dest destination ipv6 address (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
-       const ip6_addr_t *src, const ip6_addr_t *dest)
-{
-  u32_t acc = 0;
-  u32_t addr;
-  u8_t addr_part;
-
-  for (addr_part = 0; addr_part < 4; addr_part++) {
-    addr = src->addr[addr_part];
-    acc += (addr & 0xffffUL);
-    acc += ((addr >> 16) & 0xffffUL);
-    addr = dest->addr[addr_part];
-    acc += (addr & 0xffffUL);
-    acc += ((addr >> 16) & 0xffffUL);
-  }
-  /* fold down to 16 bits */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-
-  return inet_cksum_pseudo_base(p, proto, proto_len, acc);
-}
-#endif /* LWIP_IPV6 */
-
-/* ip_chksum_pseudo:
- *
- * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
- * IP addresses are expected to be in network byte order.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param src source ip address (used for checksum of pseudo header)
- * @param dst destination ip address (used for checksum of pseudo header)
- * @param proto ip protocol (used for checksum of pseudo header)
- * @param proto_len length of the ip data part (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
-       const ip_addr_t *src, const ip_addr_t *dest)
-{
-#if LWIP_IPV6
-  if (IP_IS_V6(dest)) {
-    return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest));
-  }
-#endif /* LWIP_IPV6 */
-#if LWIP_IPV4 && LWIP_IPV6
-  else
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-#if LWIP_IPV4
-  {
-    return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest));
-  }
-#endif /* LWIP_IPV4 */
-}
-
-/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
-static u16_t
-inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
-       u16_t chksum_len, u32_t acc)
-{
-  struct pbuf *q;
-  u8_t swapped = 0;
-  u16_t chklen;
-
-  /* iterate through all pbuf in chain */
-  for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
-    LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
-      (void *)q, (void *)q->next));
-    chklen = q->len;
-    if (chklen > chksum_len) {
-      chklen = chksum_len;
-    }
-    acc += LWIP_CHKSUM(q->payload, chklen);
-    chksum_len -= chklen;
-    LWIP_ASSERT("delete me", chksum_len < 0x7fff);
-    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
-    /* fold the upper bit down */
-    acc = FOLD_U32T(acc);
-    if (q->len % 2 != 0) {
-      swapped = 1 - swapped;
-      acc = SWAP_BYTES_IN_WORD(acc);
-    }
-    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
-  }
-
-  if (swapped) {
-    acc = SWAP_BYTES_IN_WORD(acc);
-  }
-
-  acc += (u32_t)lwip_htons((u16_t)proto);
-  acc += (u32_t)lwip_htons(proto_len);
-
-  /* Fold 32-bit sum to 16 bits
-     calling this twice is probably faster than if statements... */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-  LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
-  return (u16_t)~(acc & 0xffffUL);
-}
-
-#if LWIP_IPV4
-/* inet_chksum_pseudo_partial:
- *
- * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
- * IP addresses are expected to be in network byte order.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param src source ip address (used for checksum of pseudo header)
- * @param dst destination ip address (used for checksum of pseudo header)
- * @param proto ip protocol (used for checksum of pseudo header)
- * @param proto_len length of the ip data part (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
-       u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest)
-{
-  u32_t acc;
-  u32_t addr;
-
-  addr = ip4_addr_get_u32(src);
-  acc = (addr & 0xffffUL);
-  acc += ((addr >> 16) & 0xffffUL);
-  addr = ip4_addr_get_u32(dest);
-  acc += (addr & 0xffffUL);
-  acc += ((addr >> 16) & 0xffffUL);
-  /* fold down to 16 bits */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-
-  return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
-}
-#endif /* LWIP_IPV4 */
-
-#if LWIP_IPV6
-/**
- * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
- * IPv6 addresses are expected to be in network byte order. Will only compute for a
- * portion of the payload.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param proto ipv6 protocol/next header (used for checksum of pseudo header)
- * @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
- * @param chksum_len number of payload bytes used to compute chksum
- * @param src source ipv6 address (used for checksum of pseudo header)
- * @param dest destination ipv6 address (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
-       u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest)
-{
-  u32_t acc = 0;
-  u32_t addr;
-  u8_t addr_part;
-
-  for (addr_part = 0; addr_part < 4; addr_part++) {
-    addr = src->addr[addr_part];
-    acc += (addr & 0xffffUL);
-    acc += ((addr >> 16) & 0xffffUL);
-    addr = dest->addr[addr_part];
-    acc += (addr & 0xffffUL);
-    acc += ((addr >> 16) & 0xffffUL);
-  }
-  /* fold down to 16 bits */
-  acc = FOLD_U32T(acc);
-  acc = FOLD_U32T(acc);
-
-  return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
-}
-#endif /* LWIP_IPV6 */
-
-/* ip_chksum_pseudo_partial:
- *
- * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
- *
- * @param p chain of pbufs over that a checksum should be calculated (ip data part)
- * @param src source ip address (used for checksum of pseudo header)
- * @param dst destination ip address (used for checksum of pseudo header)
- * @param proto ip protocol (used for checksum of pseudo header)
- * @param proto_len length of the ip data part (used for checksum of pseudo header)
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
-       u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest)
-{
-#if LWIP_IPV6
-  if (IP_IS_V6(dest)) {
-    return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest));
-  }
-#endif /* LWIP_IPV6 */
-#if LWIP_IPV4 && LWIP_IPV6
-  else
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-#if LWIP_IPV4
-  {
-    return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest));
-  }
-#endif /* LWIP_IPV4 */
-}
-
-/* inet_chksum:
- *
- * Calculates the Internet checksum over a portion of memory. Used primarily for IP
- * and ICMP.
- *
- * @param dataptr start of the buffer to calculate the checksum (no alignment needed)
- * @param len length of the buffer to calculate the checksum
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-
-u16_t
-inet_chksum(const void *dataptr, u16_t len)
-{
-  return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len);
-}
-
-/**
- * Calculate a checksum over a chain of pbufs (without pseudo-header, much like
- * inet_chksum only pbufs are used).
- *
- * @param p pbuf chain over that the checksum should be calculated
- * @return checksum (as u16_t) to be saved directly in the protocol header
- */
-u16_t
-inet_chksum_pbuf(struct pbuf *p)
-{
-  u32_t acc;
-  struct pbuf *q;
-  u8_t swapped;
-
-  acc = 0;
-  swapped = 0;
-  for (q = p; q != NULL; q = q->next) {
-    acc += LWIP_CHKSUM(q->payload, q->len);
-    acc = FOLD_U32T(acc);
-    if (q->len % 2 != 0) {
-      swapped = 1 - swapped;
-      acc = SWAP_BYTES_IN_WORD(acc);
-    }
-  }
-
-  if (swapped) {
-    acc = SWAP_BYTES_IN_WORD(acc);
-  }
-  return (u16_t)~(acc & 0xffffUL);
-}
-
-/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
- * like MEMCPY but generates a checksum at the same time. Since this is a
- * performance-sensitive function, you might want to create your own version
- * in assembly targeted at your hardware by defining it in lwipopts.h:
- *   #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
- */
-
-#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
-/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
- * For architectures with big caches, data might still be in cache when
- * generating the checksum after copying.
- */
-u16_t
-lwip_chksum_copy(void *dst, const void *src, u16_t len)
-{
-  MEMCPY(dst, src, len);
-  return LWIP_CHKSUM(dst, len);
-}
-#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */

+ 0 - 383
components/net/lwip-2.0.0/src/core/init.c

@@ -1,383 +0,0 @@
-/**
- * @file
- * Modules initialization
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- */
-
-#include "lwip/opt.h"
-
-#include "lwip/init.h"
-#include "lwip/stats.h"
-#include "lwip/sys.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
-#include "lwip/pbuf.h"
-#include "lwip/netif.h"
-#include "lwip/sockets.h"
-#include "lwip/ip.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/priv/tcp_priv.h"
-#include "lwip/igmp.h"
-#include "lwip/dns.h"
-#include "lwip/timeouts.h"
-#include "lwip/etharp.h"
-#include "lwip/ip6.h"
-#include "lwip/nd6.h"
-#include "lwip/mld6.h"
-#include "lwip/api.h"
-
-#include "netif/ppp/ppp_opts.h"
-#include "netif/ppp/ppp_impl.h"
-
-#ifndef LWIP_SKIP_PACKING_CHECK
-
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct packed_struct_test
-{
-  PACK_STRUCT_FLD_8(u8_t  dummy1);
-  PACK_STRUCT_FIELD(u32_t dummy2);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
-#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5
-
-#endif
-
-/* Compile-time sanity checks for configuration errors.
- * These can be done independently of LWIP_DEBUG, without penalty.
- */
-#ifndef BYTE_ORDER
-  #error "BYTE_ORDER is not defined, you have to define it in your cc.h"
-#endif
-#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
-  #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP && LWIP_UDPLITE)
-  #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP && LWIP_DHCP)
-  #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
-  #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-#if (!LWIP_UDP && LWIP_DNS)
-  #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
-#endif
-#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
-#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
-  #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
-#endif
-#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
-  #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
-#endif
-#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
-  #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
-#endif
-#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
-  #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
-#endif
-#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
-  #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
-#endif
-#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
-  #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
-#endif
-#if (LWIP_IGMP && !LWIP_IPV4)
-  #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
-#endif
-#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
-  #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
-#endif
-#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
-  #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
-#endif
-/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
-#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
-  #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
-#endif
-#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
-  #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
-#endif
-#endif /* !MEMP_MEM_MALLOC */
-#if LWIP_WND_SCALE
-#if (LWIP_TCP && (TCP_WND > 0xffffffff))
-  #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
-#endif
-#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
-  #error "The maximum valid window scale value is 14!"
-#endif
-#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
-  #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
-#endif
-#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
-  #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
-#endif
-#else /* LWIP_WND_SCALE */
-#if (LWIP_TCP && (TCP_WND > 0xffff))
-  #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
-#endif
-#endif /* LWIP_WND_SCALE */
-#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
-  #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
-#endif
-#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
-  #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
-#endif
-#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
-  #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
-#endif
-#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
-  #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
-#endif
-#if (LWIP_NETIF_API && (NO_SYS==1))
-  #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
-#endif
-#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
-  #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
-#endif
-#if (LWIP_PPP_API && (NO_SYS==1))
-  #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
-#endif
-#if (LWIP_PPP_API && (PPP_SUPPORT==0))
-  #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
-#endif
-#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
-  #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
-#endif
-#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
-  #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
-#endif
-#if (!LWIP_ARP && LWIP_AUTOIP)
-  #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
-#endif
-#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
-  #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
-#endif
-#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
-  #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
-#endif
-#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
-  #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
-#endif
-#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
-  #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
-#endif
-#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
-  #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
-#endif
-#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
-  #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
-#endif
-#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
-  #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
-#endif
-#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
-  #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
-#endif
-#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
-  #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
-#endif
-#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
-  #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
-#endif
-#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
-  #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)"
-#endif
-#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
-  #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
-#endif
-#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
-  #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
-#endif
-#if LWIP_NETCONN && LWIP_TCP
-#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
-  #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
-#endif
-#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
-  #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
-#endif
-#endif /* LWIP_NETCONN && LWIP_TCP */
-#if LWIP_SOCKET
-/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
-#if SO_REUSEADDR != SOF_REUSEADDR
-  #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
-#endif
-#if SO_KEEPALIVE != SOF_KEEPALIVE
-  #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
-#endif
-#if SO_BROADCAST != SOF_BROADCAST
-  #error "WARNING: SO_BROADCAST != SOF_BROADCAST"
-#endif
-#endif /* LWIP_SOCKET */
-
-
-/* Compile-time checks for deprecated options.
- */
-#ifdef MEMP_NUM_TCPIP_MSG
-  #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
-#endif
-#ifdef TCP_REXMIT_DEBUG
-  #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
-#endif
-#ifdef RAW_STATS
-  #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
-#endif
-#ifdef ETHARP_QUEUE_FIRST
-  #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
-#endif
-#ifdef ETHARP_ALWAYS_INSERT
-  #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
-#endif
-#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
-  #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
-
-#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
-#define LWIP_DISABLE_TCP_SANITY_CHECKS  0
-#endif
-#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
-#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
-#endif
-
-/* MEMP sanity checks */
-#if MEMP_MEM_MALLOC
-#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
-#if LWIP_NETCONN || LWIP_SOCKET
-#if !MEMP_NUM_NETCONN && LWIP_SOCKET
-#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
-#endif
-#else /* MEMP_MEM_MALLOC */
-#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
-#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#endif /* LWIP_NETCONN || LWIP_SOCKET */
-#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
-#if MEM_USE_POOLS
-#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time"
-#endif
-#ifdef LWIP_HOOK_MEMP_AVAILABLE
-#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC"
-#endif
-#endif /* MEMP_MEM_MALLOC */
-
-/* TCP sanity checks */
-#if !LWIP_DISABLE_TCP_SANITY_CHECKS
-#if LWIP_TCP
-#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
-  #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if TCP_SND_BUF < (2 * TCP_MSS)
-  #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
-  #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."
-#endif
-#if TCP_SNDLOWAT >= TCP_SND_BUF
-  #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
-  #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
-#endif
-#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
-  #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
-  #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
-  #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
-#endif
-#if TCP_WND < TCP_MSS
-  #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 /* LWIP_TCP */
-#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
-
-/**
- * @ingroup lwip_nosys
- * Initialize all modules.
- * Use this in NO_SYS mode. Use tcpip_init() otherwise.
- */
-void
-lwip_init(void)
-{
-#ifndef LWIP_SKIP_PACKING_CHECK
-  LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
-#endif
-
-  /* Modules initialization */
-  stats_init();
-#if !NO_SYS
-  sys_init();
-#endif /* !NO_SYS */
-  mem_init();
-  memp_init();
-  pbuf_init();
-  netif_init();
-#if LWIP_IPV4
-  ip_init();
-#if LWIP_ARP
-  etharp_init();
-#endif /* LWIP_ARP */
-#endif /* LWIP_IPV4 */
-#if LWIP_RAW
-  raw_init();
-#endif /* LWIP_RAW */
-#if LWIP_UDP
-  udp_init();
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-  tcp_init();
-#endif /* LWIP_TCP */
-#if LWIP_IGMP
-  igmp_init();
-#endif /* LWIP_IGMP */
-#if LWIP_DNS
-  dns_init();
-#endif /* LWIP_DNS */
-#if PPP_SUPPORT
-  ppp_init();
-#endif
- 
-#if LWIP_TIMERS
-  sys_timeouts_init();
-#endif /* LWIP_TIMERS */
-}

+ 0 - 124
components/net/lwip-2.0.0/src/core/ip.c

@@ -1,124 +0,0 @@
-/**
- * @file
- * Common IPv4 and IPv6 code
- *
- * @defgroup ip IP
- * @ingroup callbackstyle_api
- * 
- * @defgroup ip4 IPv4
- * @ingroup ip
- *
- * @defgroup ip6 IPv6
- * @ingroup ip
- * 
- * @defgroup ipaddr IP address handling
- * @ingroup infrastructure
- * 
- * @defgroup ip4addr IPv4 only
- * @ingroup ipaddr
- * 
- * @defgroup ip6addr IPv6 only
- * @ingroup ipaddr
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4 || LWIP_IPV6
-
-#include "lwip/ip_addr.h"
-#include "lwip/ip.h"
-
-/** Global data for both IPv4 and IPv6 */
-struct ip_globals ip_data;
-
-#if LWIP_IPV4 && LWIP_IPV6
-
-const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
-
-/**
- * @ingroup ipaddr
- * Convert IP address string (both versions) to numeric.
- * The version is auto-detected from the string.
- *
- * @param cp IP address string to convert
- * @param addr conversion result is stored here
- * @return 1 on success, 0 on error
- */
-int
-ipaddr_aton(const char *cp, ip_addr_t *addr)
-{
-  if (cp != NULL) {
-    const char* c;
-    for (c = cp; *c != 0; c++) {
-      if (*c == ':') {
-        /* contains a colon: IPv6 address */
-        if (addr) {
-          IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
-        }
-        return ip6addr_aton(cp, ip_2_ip6(addr));
-      } else if (*c == '.') {
-        /* contains a dot: IPv4 address */
-        break;
-      }
-    }
-    /* call ip4addr_aton as fallback or if IPv4 was found */
-    if (addr) {
-      IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
-    }
-    return ip4addr_aton(cp, ip_2_ip4(addr));
-  }
-  return 0;
-}
-
-/**
- * @ingroup lwip_nosys
- * 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().
- */
-err_t
-ip_input(struct pbuf *p, struct netif *inp)
-{
-  if (p != NULL) {
-    if (IP_HDR_GET_VERSION(p->payload) == 6) {
-      return ip6_input(p, inp);
-    }
-    return ip4_input(p, inp);
-  }
-  return ERR_VAL;
-}
-
-#endif /* LWIP_IPV4 && LWIP_IPV6 */
-
-#endif /* LWIP_IPV4 || LWIP_IPV6 */

+ 0 - 529
components/net/lwip-2.0.0/src/core/ipv4/autoip.c

@@ -1,529 +0,0 @@
-/**
- * @file
- * AutoIP Automatic LinkLocal IP Configuration
- *
- * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
- * with RFC 3927.
- *
- * @defgroup autoip AUTOIP
- * @ingroup ip4
- * AUTOIP related functions
- * USAGE:
- *
- * define @ref LWIP_AUTOIP 1 in your lwipopts.h
- * Options:
- * AUTOIP_TMR_INTERVAL msecs,
- *   I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
- *   Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
- *
- * Without DHCP:
- * - Call autoip_start() after netif_add().
- *
- * With DHCP:
- * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
- * - Configure your DHCP Client.
- * 
- * @see netifapi_autoip
- */
-
-/*
- *
- * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * Author: Dominik Spies <kontakt@dspies.de>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/mem.h"
-/* #include "lwip/udp.h" */
-#include "lwip/ip_addr.h"
-#include "lwip/netif.h"
-#include "lwip/autoip.h"
-#include "lwip/etharp.h"
-#include "lwip/prot/autoip.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/** Pseudo random macro based on netif informations.
- * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
-#ifndef LWIP_AUTOIP_RAND
-#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
-                                   ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
-                                   ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
-                                   ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
-                                   (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0))
-#endif /* LWIP_AUTOIP_RAND */
-
-/**
- * Macro that generates the initial IP address to be tried by AUTOIP.
- * If you want to override this, define it to something else in lwipopts.h.
- */
-#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
-#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
-  lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
-                 ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
-#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
-
-/* static functions */
-static err_t autoip_arp_announce(struct netif *netif);
-static void autoip_start_probing(struct netif *netif);
-
-#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
-
-/**
- * @ingroup autoip 
- * Set a statically allocated struct autoip to work with.
- * Using this prevents autoip_start to allocate it using mem_malloc.
- *
- * @param netif the netif for which to set the struct autoip
- * @param autoip (uninitialised) autoip struct allocated by the application
- */
-void
-autoip_set_struct(struct netif *netif, struct autoip *autoip)
-{
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-  LWIP_ASSERT("autoip != NULL", autoip != NULL);
-  LWIP_ASSERT("netif already has a struct autoip set",
-              netif_autoip_data(netif) == NULL);
-
-  /* clear data structure */
-  memset(autoip, 0, sizeof(struct autoip));
-  /* autoip->state = AUTOIP_STATE_OFF; */
-  netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
-}
-
-/** Restart AutoIP client and check the next address (conflict detected)
- *
- * @param netif The netif under AutoIP control
- */
-static void
-autoip_restart(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-  autoip->tried_llipaddr++;
-  autoip_start(netif);
-}
-
-/**
- * Handle a IP address conflict after an ARP conflict detection
- */
-static void
-autoip_handle_arp_conflict(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where
-     a) means retreat on the first conflict and
-     b) allows to keep an already configured address when having only one
-        conflict in 10 seconds
-     We use option b) since it helps to improve the chance that one of the two
-     conflicting hosts may be able to retain its address. */
-
-  if (autoip->lastconflict > 0) {
-    /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */
-    LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-      ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
-
-    /* Active TCP sessions are aborted when removing the ip addresss */
-    autoip_restart(netif);
-  } else {
-    LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-      ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
-    autoip_arp_announce(netif);
-    autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
-  }
-}
-
-/**
- * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
- *
- * @param netif network interface on which create the IP-Address
- * @param ipaddr ip address to initialize
- */
-static void
-autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
-   * compliant to RFC 3927 Section 2.1
-   * We have 254 * 256 possibilities */
-
-  u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
-  addr += autoip->tried_llipaddr;
-  addr = AUTOIP_NET | (addr & 0xffff);
-  /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
-
-  if (addr < AUTOIP_RANGE_START) {
-    addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
-  }
-  if (addr > AUTOIP_RANGE_END) {
-    addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
-  }
-  LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
-    (addr <= AUTOIP_RANGE_END));
-  ip4_addr_set_u32(ipaddr, lwip_htonl(addr));
-
-  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-    ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-    (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
-    ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
-}
-
-/**
- * Sends an ARP probe from a network interface
- *
- * @param netif network interface used to send the probe
- */
-static err_t
-autoip_arp_probe(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-  /* this works because netif->ip_addr is ANY */
-  return etharp_request(netif, &autoip->llipaddr);
-}
-
-/**
- * Sends an ARP announce from a network interface
- *
- * @param netif network interface used to send the announce
- */
-static err_t
-autoip_arp_announce(struct netif *netif)
-{
-  return etharp_gratuitous(netif);
-}
-
-/**
- * Configure interface for use with current LL IP-Address
- *
- * @param netif network interface to configure with current LL IP-Address
- */
-static err_t
-autoip_bind(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-  ip4_addr_t sn_mask, gw_addr;
-
-  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
-    ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-    (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
-    ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
-    ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
-
-  IP4_ADDR(&sn_mask, 255, 255, 0, 0);
-  IP4_ADDR(&gw_addr, 0, 0, 0, 0);
-
-  netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
-  /* interface is used by routing now that an address is set */
-
-  return ERR_OK;
-}
-
-/**
- * @ingroup autoip 
- * Start AutoIP client
- *
- * @param netif network interface on which start the AutoIP client
- */
-err_t
-autoip_start(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-  err_t result = ERR_OK;
-
-  LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
-
-  /* Set IP-Address, Netmask and Gateway to 0 to make sure that
-   * ARP Packets are formed correctly
-   */
-  netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
-
-  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-    ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
-    netif->name[1], (u16_t)netif->num));
-  if (autoip == NULL) {
-    /* no AutoIP client attached yet? */
-    LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
-      ("autoip_start(): starting new AUTOIP client\n"));
-    autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
-    if (autoip == NULL) {
-      LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
-        ("autoip_start(): could not allocate autoip\n"));
-      return ERR_MEM;
-    }
-    memset(autoip, 0, sizeof(struct autoip));
-    /* store this AutoIP client in the netif */
-    netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
-    LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
-  } else {
-    autoip->state = AUTOIP_STATE_OFF;
-    autoip->ttw = 0;
-    autoip->sent_num = 0;
-    ip4_addr_set_zero(&autoip->llipaddr);
-    autoip->lastconflict = 0;
-  }
-
-  autoip_create_addr(netif, &(autoip->llipaddr));
-  autoip_start_probing(netif);
-
-  return result;
-}
-
-static void
-autoip_start_probing(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  autoip->state = AUTOIP_STATE_PROBING;
-  autoip->sent_num = 0;
-  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-     ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
-      ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
-
-  /* time to wait to first probe, this is randomly
-   * chosen out of 0 to PROBE_WAIT seconds.
-   * compliant to RFC 3927 Section 2.2.1
-   */
-  autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
-
-  /*
-   * if we tried more then MAX_CONFLICTS we must limit our rate for
-   * acquiring and probing address
-   * compliant to RFC 3927 Section 2.2.1
-   */
-  if (autoip->tried_llipaddr > MAX_CONFLICTS) {
-    autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
-  }
-}
-
-/**
- * Handle a possible change in the network configuration.
- *
- * If there is an AutoIP address configured, take the interface down
- * and begin probing with the same address.
- */
-void
-autoip_network_changed(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  if (autoip && (autoip->state != AUTOIP_STATE_OFF)) {
-    autoip_start_probing(netif);
-  }
-}
-
-/**
- * @ingroup autoip 
- * Stop AutoIP client
- *
- * @param netif network interface on which stop the AutoIP client
- */
-err_t
-autoip_stop(struct netif *netif)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  if (autoip != NULL) {
-    autoip->state = AUTOIP_STATE_OFF;
-    if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
-      netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
-    }
-  }
-  return ERR_OK;
-}
-
-/**
- * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
- */
-void
-autoip_tmr(void)
-{
-  struct netif *netif = netif_list;
-  /* loop through netif's */
-  while (netif != NULL) {
-    struct autoip* autoip = netif_autoip_data(netif);
-    /* only act on AutoIP configured interfaces */
-    if (autoip != NULL) {
-      if (autoip->lastconflict > 0) {
-        autoip->lastconflict--;
-      }
-
-      LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
-        ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
-        (u16_t)(autoip->state), autoip->ttw));
-
-      if (autoip->ttw > 0) {
-        autoip->ttw--;
-      }
-
-      switch(autoip->state) {
-        case AUTOIP_STATE_PROBING:
-          if (autoip->ttw == 0) {
-            if (autoip->sent_num >= PROBE_NUM) {
-              /* Switch to ANNOUNCING: now we can bind to an IP address and use it */
-              autoip->state = AUTOIP_STATE_ANNOUNCING;
-              autoip_bind(netif);
-              /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP
-                 which counts as an announcement */
-              autoip->sent_num = 1;
-              autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
-              LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-                 ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-                  ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
-                  ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
-            } else {
-              autoip_arp_probe(netif);
-              LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n"));
-              autoip->sent_num++;
-              if (autoip->sent_num == PROBE_NUM) {
-                /* calculate time to wait to for announce */
-                autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
-              } else {
-                /* calculate time to wait to next probe */
-                autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
-                  ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
-                  PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
-              }
-            }
-          }
-          break;
-
-        case AUTOIP_STATE_ANNOUNCING:
-          if (autoip->ttw == 0) {
-            autoip_arp_announce(netif);
-            LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n"));
-            autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
-            autoip->sent_num++;
-
-            if (autoip->sent_num >= ANNOUNCE_NUM) {
-                autoip->state = AUTOIP_STATE_BOUND;
-                autoip->sent_num = 0;
-                autoip->ttw = 0;
-                 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-                    ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-                     ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
-                     ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
-            }
-          }
-          break;
-
-        default:
-          /* nothing to do in other states */
-          break;
-      }
-    }
-    /* proceed to next network interface */
-    netif = netif->next;
-  }
-}
-
-/**
- * Handles every incoming ARP Packet, called by etharp_input().
- *
- * @param netif network interface to use for autoip processing
- * @param hdr Incoming ARP packet
- */
-void
-autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-
-  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
-  if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) {
-   /* when ip.src == llipaddr && hw.src != netif->hwaddr
-    *
-    * when probing  ip.dst == llipaddr && hw.src != netif->hwaddr
-    * we have a conflict and must solve it
-    */
-    ip4_addr_t sipaddr, dipaddr;
-    struct eth_addr netifaddr;
-    ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
-
-    /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
-     * structure packing (not using structure copy which breaks strict-aliasing rules).
-     */
-    IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
-    IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
-
-    if (autoip->state == AUTOIP_STATE_PROBING) {
-     /* RFC 3927 Section 2.2.1:
-      * from beginning to after ANNOUNCE_WAIT
-      * seconds we have a conflict if
-      * ip.src == llipaddr OR
-      * ip.dst == llipaddr && hw.src != own hwaddr
-      */
-      if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
-          (ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
-           !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
-        LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
-          ("autoip_arp_reply(): Probe Conflict detected\n"));
-        autoip_restart(netif);
-      }
-    } else {
-     /* RFC 3927 Section 2.5:
-      * in any state we have a conflict if
-      * ip.src == llipaddr && hw.src != own hwaddr
-      */
-      if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) &&
-          !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
-        LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
-          ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
-        autoip_handle_arp_conflict(netif);
-      }
-    }
-  }
-}
-
-/** check if AutoIP supplied netif->ip_addr
- *
- * @param netif the netif to check
- * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING),
- *         0 otherwise
- */
-u8_t
-autoip_supplied_address(const struct netif *netif)
-{
-  if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) {
-    struct autoip* autoip = netif_autoip_data(netif);
-    return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING);
-  }
-  return 0;
-}
-
-u8_t
-autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr)
-{
-  struct autoip* autoip = netif_autoip_data(netif);
-  return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr));
-}
-
-#endif /* LWIP_IPV4 && LWIP_AUTOIP */

+ 0 - 1932
components/net/lwip-2.0.0/src/core/ipv4/dhcp.c

@@ -1,1932 +0,0 @@
-/**
- * @file
- * Dynamic Host Configuration Protocol client
- *
- * @defgroup dhcp4 DHCPv4
- * @ingroup ip4
- * DHCP (IPv4) related functions
- * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
- * with RFC 2131 and RFC 2132.
- *
- * @todo:
- * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
- *
- * Options:
- * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
- * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
- *
- * dhcp_start() starts a DHCP client instance which
- * configures the interface by obtaining an IP address lease and maintaining it.
- *
- * Use dhcp_release() to end the lease and use dhcp_stop()
- * to remove the DHCP client.
- *
- * @see netifapi_dhcp4
- */
-
-/*
- * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
- * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * The Swedish Institute of Computer Science and Adam Dunkels
- * are specifically granted permission to redistribute this
- * source code.
- *
- * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/stats.h"
-#include "lwip/mem.h"
-#include "lwip/udp.h"
-#include "lwip/ip_addr.h"
-#include "lwip/netif.h"
-#include "lwip/def.h"
-#include "lwip/dhcp.h"
-#include "lwip/autoip.h"
-#include "lwip/dns.h"
-#include "lwip/etharp.h"
-#include "lwip/prot/dhcp.h"
-
-#include <string.h>
-
-/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using
- * LWIP_RAND() (this overrides DHCP_GLOBAL_XID)
- */
-#ifndef DHCP_CREATE_RAND_XID
-#define DHCP_CREATE_RAND_XID        1
-#endif
-
-/** Default for DHCP_GLOBAL_XID is 0xABCD0000
- * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
- *  \#define DHCP_GLOBAL_XID_HEADER "stdlib.h"
- *  \#define DHCP_GLOBAL_XID rand()
- */
-#ifdef DHCP_GLOBAL_XID_HEADER
-#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
-#endif
-
-/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
- * MTU is checked to be big enough in dhcp_start */
-#define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
-#define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
-/** Minimum length for reply before packet is parsed */
-#define DHCP_MIN_REPLY_LEN             44
-
-#define REBOOT_TRIES                2
-
-/** Option handling: options are parsed in dhcp_parse_reply
- * and saved in an array where other functions can load them from.
- * This might be moved into the struct dhcp (not necessarily since
- * lwIP is single-threaded and the array is only used while in recv
- * callback). */
-#define DHCP_OPTION_IDX_OVERLOAD    0
-#define DHCP_OPTION_IDX_MSG_TYPE    1
-#define DHCP_OPTION_IDX_SERVER_ID   2
-#define DHCP_OPTION_IDX_LEASE_TIME  3
-#define DHCP_OPTION_IDX_T1          4
-#define DHCP_OPTION_IDX_T2          5
-#define DHCP_OPTION_IDX_SUBNET_MASK 6
-#define DHCP_OPTION_IDX_ROUTER      7
-#define DHCP_OPTION_IDX_DNS_SERVER  8
-#if LWIP_DHCP_GET_NTP_SRV
-#define DHCP_OPTION_IDX_NTP_SERVER  (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
-#define DHCP_OPTION_IDX_MAX         (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS)
-#else /* LWIP_DHCP_GET_NTP_SRV */
-#define DHCP_OPTION_IDX_MAX         (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
-#endif /* LWIP_DHCP_GET_NTP_SRV */
-
-/** Holds the decoded option values, only valid while in dhcp_recv.
-    @todo: move this into struct dhcp? */
-u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
-/** Holds a flag which option was received and is contained in dhcp_rx_options_val,
-    only valid while in dhcp_recv.
-    @todo: move this into struct dhcp? */
-u8_t  dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
-
-static u8_t dhcp_discover_request_options[] = {
-  DHCP_OPTION_SUBNET_MASK,
-  DHCP_OPTION_ROUTER,
-  DHCP_OPTION_BROADCAST,
-  DHCP_OPTION_DNS_SERVER
-#if LWIP_DHCP_GET_NTP_SRV
-  , DHCP_OPTION_NTP
-#endif /* LWIP_DHCP_GET_NTP_SRV */
-  };
-
-#ifdef DHCP_GLOBAL_XID
-static u32_t xid;
-static u8_t xid_initialised;
-#endif /* DHCP_GLOBAL_XID */
-
-#define dhcp_option_given(dhcp, idx)          (dhcp_rx_options_given[idx] != 0)
-#define dhcp_got_option(dhcp, idx)            (dhcp_rx_options_given[idx] = 1)
-#define dhcp_clear_option(dhcp, idx)          (dhcp_rx_options_given[idx] = 0)
-#define dhcp_clear_all_options(dhcp)          (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
-#define dhcp_get_option_value(dhcp, idx)      (dhcp_rx_options_val[idx])
-#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
-
-static struct udp_pcb *dhcp_pcb;
-static u8_t dhcp_pcb_refcount;
-
-/* DHCP client state machine functions */
-static err_t dhcp_discover(struct netif *netif);
-static err_t dhcp_select(struct netif *netif);
-static void dhcp_bind(struct netif *netif);
-#if DHCP_DOES_ARP_CHECK
-static err_t dhcp_decline(struct netif *netif);
-#endif /* DHCP_DOES_ARP_CHECK */
-static err_t dhcp_rebind(struct netif *netif);
-static err_t dhcp_reboot(struct netif *netif);
-static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
-
-/* receive, unfold, parse and free incoming messages */
-static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
-
-/* set the DHCP timers */
-static void dhcp_timeout(struct netif *netif);
-static void dhcp_t1_timeout(struct netif *netif);
-static void dhcp_t2_timeout(struct netif *netif);
-
-/* build outgoing messages */
-/* create a DHCP message, fill in common headers */
-static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type);
-/* free a DHCP request */
-static void dhcp_delete_msg(struct dhcp *dhcp);
-/* add a DHCP option (type, then length in bytes) */
-static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
-/* add option values */
-static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
-static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
-static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
-#if LWIP_NETIF_HOSTNAME
-static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif);
-#endif /* LWIP_NETIF_HOSTNAME */
-/* always add the DHCP options trailer to end and pad */
-static void dhcp_option_trailer(struct dhcp *dhcp);
-
-#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
-
-/** Ensure DHCP PCB is allocated and bound */
-static err_t
-dhcp_inc_pcb_refcount(void)
-{
-  if (dhcp_pcb_refcount == 0) {
-    LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL);
-
-    /* allocate UDP PCB */
-    dhcp_pcb = udp_new();
-
-    if (dhcp_pcb == NULL) {
-      return ERR_MEM;
-    }
-
-    ip_set_option(dhcp_pcb, SOF_BROADCAST);
-
-    /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
-    udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT);
-    udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT);
-    udp_recv(dhcp_pcb, dhcp_recv, NULL);
-  }
-
-  dhcp_pcb_refcount++;
-
-  return ERR_OK;
-}
-
-/** Free DHCP PCB if the last netif stops using it */
-static void
-dhcp_dec_pcb_refcount(void)
-{
-  LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0));
-  dhcp_pcb_refcount--;
-
-  if (dhcp_pcb_refcount == 0) {
-    udp_remove(dhcp_pcb);
-    dhcp_pcb = NULL;
-  }
-}
-
-/**
- * Back-off the DHCP client (because of a received NAK response).
- *
- * Back-off the DHCP client because of a received NAK. Receiving a
- * NAK means the client asked for something non-sensible, for
- * example when it tries to renew a lease obtained on another network.
- *
- * We clear any existing set IP address and restart DHCP negotiation
- * afresh (as per RFC2131 3.2.3).
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_handle_nak(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
-    (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
-  /* Change to a defined state - set this before assigning the address
-     to ensure the callback can use dhcp_supplied_address() */
-  dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
-  /* remove IP address from interface (must no longer be used, as per RFC2131) */
-  netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
-  /* We can immediately restart discovery */
-  dhcp_discover(netif);
-}
-
-#if DHCP_DOES_ARP_CHECK
-/**
- * Checks if the offered IP address is already in use.
- *
- * It does so by sending an ARP request for the offered address and
- * entering CHECKING state. If no ARP reply is received within a small
- * interval, the address is assumed to be free for use by us.
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_check(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  u16_t msecs;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
-    (s16_t)netif->name[1]));
-  dhcp_set_state(dhcp, DHCP_STATE_CHECKING);
-  /* create an ARP query for the offered IP address, expecting that no host
-     responds, as the IP address should not be in use. */
-  result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
-  if (result != ERR_OK) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  msecs = 500;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
-}
-#endif /* DHCP_DOES_ARP_CHECK */
-
-/**
- * Remember the configuration offered by a DHCP server.
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_handle_offer(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
-    (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
-  /* obtain the server address */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
-    ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
-      ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
-    /* remember offered address */
-    ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
-      ip4_addr_get_u32(&dhcp->offered_ip_addr)));
-
-    dhcp_select(netif);
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
-      ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif));
-  }
-}
-
-/**
- * Select a DHCP server offer out of all offers.
- *
- * Simply select the first offer received.
- *
- * @param netif the netif under DHCP control
- * @return lwIP specific error (see error.h)
- */
-static err_t
-dhcp_select(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  u16_t msecs;
-  u8_t i;
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
-  dhcp_set_state(dhcp, DHCP_STATE_REQUESTING);
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
-
-    /* MUST request the offered IP address */
-    dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
-    dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
-
-    dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
-    dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
-
-    dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
-    for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
-      dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
-    }
-
-#if LWIP_NETIF_HOSTNAME
-    dhcp_option_hostname(dhcp, netif);
-#endif /* LWIP_NETIF_HOSTNAME */
-
-    dhcp_option_trailer(dhcp);
-    /* shrink the pbuf to the actual content length */
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    /* send broadcast to any DHCP server */
-    udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-
-/**
- * The DHCP timer that checks for lease renewal/rebind timeouts.
- * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS).
- */
-void
-dhcp_coarse_tmr(void)
-{
-  struct netif *netif = netif_list;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
-  /* iterate through all network interfaces */
-  while (netif != NULL) {
-    /* only act on DHCP configured interfaces */
-    struct dhcp *dhcp = netif_dhcp_data(netif);
-    if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) {
-      /* compare lease time to expire timeout */
-      if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) {
-        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n"));
-        /* this clients' lease time has expired */
-        dhcp_release(netif);
-        dhcp_discover(netif);
-      /* timer is active (non zero), and triggers (zeroes) now? */
-      } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) {
-        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
-        /* this clients' rebind timeout triggered */
-        dhcp_t2_timeout(netif);
-      /* timer is active (non zero), and triggers (zeroes) now */
-      } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) {
-        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
-        /* this clients' renewal timeout triggered */
-        dhcp_t1_timeout(netif);
-      }
-    }
-    /* proceed to next netif */
-    netif = netif->next;
-  }
-}
-
-/**
- * DHCP transaction timeout handling (this function must be called every 500ms,
- * see @ref DHCP_FINE_TIMER_MSECS).
- *
- * A DHCP server is expected to respond within a short period of time.
- * This timer checks whether an outstanding DHCP request is timed out.
- */
-void
-dhcp_fine_tmr(void)
-{
-  struct netif *netif = netif_list;
-  /* loop through netif's */
-  while (netif != NULL) {
-    struct dhcp *dhcp = netif_dhcp_data(netif);
-    /* only act on DHCP configured interfaces */
-    if (dhcp != NULL) {
-      /* timer is active (non zero), and is about to trigger now */
-      if (dhcp->request_timeout > 1) {
-        dhcp->request_timeout--;
-      }
-      else if (dhcp->request_timeout == 1) {
-        dhcp->request_timeout--;
-        /* { netif->dhcp->request_timeout == 0 } */
-        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
-        /* this client's request timeout triggered */
-        dhcp_timeout(netif);
-      }
-    }
-    /* proceed to next network interface */
-    netif = netif->next;
-  }
-}
-
-/**
- * A DHCP negotiation transaction, or ARP request, has timed out.
- *
- * The timer that was started with the DHCP or ARP request has
- * timed out, indicating no response was received in time.
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_timeout(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
-  /* back-off period has passed, or server selection timed out */
-  if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
-    dhcp_discover(netif);
-  /* receiving the requested lease timed out */
-  } else if (dhcp->state == DHCP_STATE_REQUESTING) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
-    if (dhcp->tries <= 5) {
-      dhcp_select(netif);
-    } else {
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
-      dhcp_release(netif);
-      dhcp_discover(netif);
-    }
-#if DHCP_DOES_ARP_CHECK
-  /* received no ARP reply for the offered address (which is good) */
-  } else if (dhcp->state == DHCP_STATE_CHECKING) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
-    if (dhcp->tries <= 1) {
-      dhcp_check(netif);
-    /* no ARP replies on the offered address,
-       looks like the IP address is indeed free */
-    } else {
-      /* bind the interface to the offered address */
-      dhcp_bind(netif);
-    }
-#endif /* DHCP_DOES_ARP_CHECK */
-  } else if (dhcp->state == DHCP_STATE_REBOOTING) {
-    if (dhcp->tries < REBOOT_TRIES) {
-      dhcp_reboot(netif);
-    } else {
-      dhcp_discover(netif);
-    }
-  }
-}
-
-/**
- * The renewal period has timed out.
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_t1_timeout(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
-  if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
-      (dhcp->state == DHCP_STATE_RENEWING)) {
-    /* just retry to renew - note that the rebind timer (t2) will
-     * eventually time-out if renew tries fail. */
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-                ("dhcp_t1_timeout(): must renew\n"));
-    /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
-       DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
-    dhcp_renew(netif);
-    /* Calculate next timeout */
-    if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
-    {
-       dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2);
-    }
-  }
-}
-
-/**
- * The rebind period has timed out.
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_t2_timeout(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
-  if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
-      (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) {
-    /* just retry to rebind */
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
-                ("dhcp_t2_timeout(): must rebind\n"));
-    /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
-       DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
-    dhcp_rebind(netif);
-    /* Calculate next timeout */
-    if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
-    {
-       dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2);
-    }
-  }
-}
-
-/**
- * Handle a DHCP ACK packet
- *
- * @param netif the netif under DHCP control
- */
-static void
-dhcp_handle_ack(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-#if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV
-  u8_t n;
-#endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */
-#if LWIP_DHCP_GET_NTP_SRV
-  ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
-#endif
-
-  /* clear options we might not get from the ACK */
-  ip4_addr_set_zero(&dhcp->offered_sn_mask);
-  ip4_addr_set_zero(&dhcp->offered_gw_addr);
-#if LWIP_DHCP_BOOTP_FILE
-  ip4_addr_set_zero(&dhcp->offered_si_addr);
-#endif /* LWIP_DHCP_BOOTP_FILE */
-
-  /* lease time given? */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
-    /* remember offered lease time */
-    dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
-  }
-  /* renewal period given? */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
-    /* remember given renewal period */
-    dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
-  } else {
-    /* calculate safe periods for renewal */
-    dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
-  }
-
-  /* renewal period given? */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
-    /* remember given rebind period */
-    dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
-  } else {
-    /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/
-    dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U;
-  }
-
-  /* (y)our internet address */
-  ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
-
-#if LWIP_DHCP_BOOTP_FILE
-  /* copy boot server address,
-     boot file name copied in dhcp_parse_reply if not overloaded */
-  ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
-#endif /* LWIP_DHCP_BOOTP_FILE */
-
-  /* subnet mask given? */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
-    /* remember given subnet mask */
-    ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
-    dhcp->subnet_mask_given = 1;
-  } else {
-    dhcp->subnet_mask_given = 0;
-  }
-
-  /* gateway router */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
-    ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
-  }
-
-#if LWIP_DHCP_GET_NTP_SRV
-  /* NTP servers */
-  for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) {
-    ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
-  }
-  dhcp_set_ntp_servers(n, ntp_server_addrs);
-#endif /* LWIP_DHCP_GET_NTP_SRV */
-
-#if LWIP_DNS
-  /* DNS servers */
-  for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
-    ip_addr_t dns_addr;
-    ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
-    dns_setserver(n, &dns_addr);
-  }
-#endif /* LWIP_DNS */
-}
-
-/**
- * @ingroup dhcp4
- * Set a statically allocated struct dhcp to work with.
- * Using this prevents dhcp_start to allocate it using mem_malloc.
- *
- * @param netif the netif for which to set the struct dhcp
- * @param dhcp (uninitialised) dhcp struct allocated by the application
- */
-void
-dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
-{
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-  LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
-  LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL);
-
-  /* clear data structure */
-  memset(dhcp, 0, sizeof(struct dhcp));
-  /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
-  netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
-}
-
-/**
- * @ingroup dhcp4
- * Removes a struct dhcp from a netif.
- *
- * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
- *            struct dhcp since the memory is passed back to the heap.
- *
- * @param netif the netif from which to remove the struct dhcp
- */
-void dhcp_cleanup(struct netif *netif)
-{
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-
-  if (netif_dhcp_data(netif) != NULL) {
-    mem_free(netif_dhcp_data(netif));
-    netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
-  }
-}
-
-/**
- * @ingroup dhcp4
- * Start DHCP negotiation for a network interface.
- *
- * If no DHCP client instance was attached to this interface,
- * a new client is created first. If a DHCP client instance
- * was already present, it restarts negotiation.
- *
- * @param netif The lwIP network interface
- * @return lwIP error code
- * - ERR_OK - No error
- * - ERR_MEM - Out of memory
- */
-err_t
-dhcp_start(struct netif *netif)
-{
-  struct dhcp *dhcp;
-  err_t result;
-
-  LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
-  LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
-  dhcp = netif_dhcp_data(netif);
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
-
-  /* check MTU of the netif */
-  if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
-    return ERR_MEM;
-  }
-
-  /* no DHCP client attached yet? */
-  if (dhcp == NULL) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
-    dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
-    if (dhcp == NULL) {
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
-      return ERR_MEM;
-    }
-
-    /* store this dhcp client in the netif */
-    netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
-  /* already has DHCP client attached */
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
-    LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
-    LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
-
-    if (dhcp->pcb_allocated != 0) {
-      dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
-    }
-    /* dhcp is cleared below, no need to reset flag*/
-  }
-
-  /* clear data structure */
-  memset(dhcp, 0, sizeof(struct dhcp));
-  /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
-
-  if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
-    return ERR_MEM;
-  }
-  dhcp->pcb_allocated = 1;
-
-#if LWIP_DHCP_CHECK_LINK_UP
-  if (!netif_is_link_up(netif)) {
-    /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */
-    dhcp_set_state(dhcp, DHCP_STATE_INIT);
-    return ERR_OK;
-  }
-#endif /* LWIP_DHCP_CHECK_LINK_UP */
-
-
-  /* (re)start the DHCP negotiation */
-  result = dhcp_discover(netif);
-  if (result != ERR_OK) {
-    /* free resources allocated above */
-    dhcp_stop(netif);
-    return ERR_MEM;
-  }
-  return result;
-}
-
-/**
- * @ingroup dhcp4
- * Inform a DHCP server of our manual configuration.
- *
- * This informs DHCP servers of our fixed IP address configuration
- * by sending an INFORM message. It does not involve DHCP address
- * configuration, it is just here to be nice to the network.
- *
- * @param netif The lwIP network interface
- */
-void
-dhcp_inform(struct netif *netif)
-{
-  struct dhcp dhcp;
-  err_t result = ERR_OK;
-
-  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
-
-  if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
-    return;
-  }
-
-  memset(&dhcp, 0, sizeof(struct dhcp));
-  dhcp_set_state(&dhcp, DHCP_STATE_INFORMING);
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM);
-  if (result == ERR_OK) {
-    dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif));
-
-    dhcp_option_trailer(&dhcp);
-
-    pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
-
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
-
-    udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
-
-    dhcp_delete_msg(&dhcp);
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
-  }
-
-  dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */
-}
-
-/** Handle a possible change in the network configuration.
- *
- * This enters the REBOOTING state to verify that the currently bound
- * address is still valid.
- */
-void
-dhcp_network_changed(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-
-  if (!dhcp)
-    return;
-  switch (dhcp->state) {
-  case DHCP_STATE_REBINDING:
-  case DHCP_STATE_RENEWING:
-  case DHCP_STATE_BOUND:
-  case DHCP_STATE_REBOOTING:
-    dhcp->tries = 0;
-    dhcp_reboot(netif);
-    break;
-  case DHCP_STATE_OFF:
-    /* stay off */
-    break;
-  default:
-    /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the
-       state changes, SELECTING: continue with current 'rid' as we stay in the
-       same state */
-#if LWIP_DHCP_AUTOIP_COOP
-    if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
-      autoip_stop(netif);
-      dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
-    }
-#endif /* LWIP_DHCP_AUTOIP_COOP */
-    /* ensure we start with short timeouts, even if already discovering */
-    dhcp->tries = 0;
-    dhcp_discover(netif);
-    break;
-  }
-}
-
-#if DHCP_DOES_ARP_CHECK
-/**
- * Match an ARP reply with the offered IP address:
- * check whether the offered IP address is not in use using ARP
- *
- * @param netif the network interface on which the reply was received
- * @param addr The IP address we received a reply from
- */
-void
-dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
-{
-  struct dhcp *dhcp;
-
-  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
-  dhcp = netif_dhcp_data(netif);
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
-  /* is a DHCP client doing an ARP check? */
-  if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
-      ip4_addr_get_u32(addr)));
-    /* did a host respond with the address we
-       were offered by the DHCP server? */
-    if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) {
-      /* we will not accept the offered address */
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
-        ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
-      dhcp_decline(netif);
-    }
-  }
-}
-
-/**
- * Decline an offered lease.
- *
- * Tell the DHCP server we do not accept the offered address.
- * One reason to decline the lease is when we find out the address
- * is already in use by another host (through ARP).
- *
- * @param netif the netif under DHCP control
- */
-static err_t
-dhcp_decline(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result = ERR_OK;
-  u16_t msecs;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
-  dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
-    dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
-
-    dhcp_option_trailer(dhcp);
-    /* resize pbuf to reflect true size of options */
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    /* per section 4.4.4, broadcast DECLINE messages */
-    udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
-      ("dhcp_decline: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  msecs = 10*1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-#endif /* DHCP_DOES_ARP_CHECK */
-
-
-/**
- * Start the DHCP process, discover a DHCP server.
- *
- * @param netif the netif under DHCP control
- */
-static err_t
-dhcp_discover(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result = ERR_OK;
-  u16_t msecs;
-  u8_t i;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
-  ip4_addr_set_any(&dhcp->offered_ip_addr);
-  dhcp_set_state(dhcp, DHCP_STATE_SELECTING);
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
-  if (result == ERR_OK) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
-
-    dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
-
-    dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
-    for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
-      dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
-    }
-    dhcp_option_trailer(dhcp);
-
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
-    udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-#if LWIP_DHCP_AUTOIP_COOP
-  if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
-    dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
-    autoip_start(netif);
-  }
-#endif /* LWIP_DHCP_AUTOIP_COOP */
-  msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-
-
-/**
- * Bind the interface to the offered IP address.
- *
- * @param netif network interface to bind to the offered address
- */
-static void
-dhcp_bind(struct netif *netif)
-{
-  u32_t timeout;
-  struct dhcp *dhcp;
-  ip4_addr_t sn_mask, gw_addr;
-  LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
-  dhcp = netif_dhcp_data(netif);
-  LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
-
-  /* reset time used of lease */
-  dhcp->lease_used = 0;
-
-  if (dhcp->offered_t0_lease != 0xffffffffUL) {
-     /* set renewal period timer */
-     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
-     timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
-     if (timeout > 0xffff) {
-       timeout = 0xffff;
-     }
-     dhcp->t0_timeout = (u16_t)timeout;
-     if (dhcp->t0_timeout == 0) {
-       dhcp->t0_timeout = 1;
-     }
-     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000));
-  }
-
-  /* temporary DHCP lease? */
-  if (dhcp->offered_t1_renew != 0xffffffffUL) {
-    /* set renewal period timer */
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
-    timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
-    if (timeout > 0xffff) {
-      timeout = 0xffff;
-    }
-    dhcp->t1_timeout = (u16_t)timeout;
-    if (dhcp->t1_timeout == 0) {
-      dhcp->t1_timeout = 1;
-    }
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
-    dhcp->t1_renew_time = dhcp->t1_timeout;
-  }
-  /* set renewal period timer */
-  if (dhcp->offered_t2_rebind != 0xffffffffUL) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
-    timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
-    if (timeout > 0xffff) {
-      timeout = 0xffff;
-    }
-    dhcp->t2_timeout = (u16_t)timeout;
-    if (dhcp->t2_timeout == 0) {
-      dhcp->t2_timeout = 1;
-    }
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
-    dhcp->t2_rebind_time = dhcp->t2_timeout;
-  }
-
-  /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
-  if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
-    dhcp->t1_timeout = 0;
-  }
-
-  if (dhcp->subnet_mask_given) {
-    /* copy offered network mask */
-    ip4_addr_copy(sn_mask, dhcp->offered_sn_mask);
-  } else {
-    /* subnet mask not given, choose a safe subnet mask given the network class */
-    u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
-    if (first_octet <= 127) {
-      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
-    } else if (first_octet >= 192) {
-      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
-    } else {
-      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
-    }
-  }
-
-  ip4_addr_copy(gw_addr, dhcp->offered_gw_addr);
-  /* gateway address not given? */
-  if (ip4_addr_isany_val(gw_addr)) {
-    /* copy network address */
-    ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
-    /* use first host address on network as gateway */
-    ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
-  }
-
-#if LWIP_DHCP_AUTOIP_COOP
-  if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
-    autoip_stop(netif);
-    dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
-  }
-#endif /* LWIP_DHCP_AUTOIP_COOP */
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n",
-    ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr)));
-  /* netif is now bound to DHCP leased address - set this before assigning the address
-     to ensure the callback can use dhcp_supplied_address() */
-  dhcp_set_state(dhcp, DHCP_STATE_BOUND);
-
-  netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr);
-  /* interface is used by routing now that an address is set */
-}
-
-/**
- * @ingroup dhcp4
- * Renew an existing DHCP lease at the involved DHCP server.
- *
- * @param netif network interface which must renew its lease
- */
-err_t
-dhcp_renew(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  u16_t msecs;
-  u8_t i;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
-  dhcp_set_state(dhcp, DHCP_STATE_RENEWING);
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
-
-    dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
-    for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
-      dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
-    }
-
-#if LWIP_NETIF_HOSTNAME
-    dhcp_option_hostname(dhcp, netif);
-#endif /* LWIP_NETIF_HOSTNAME */
-
-    /* append DHCP message trailer */
-    dhcp_option_trailer(dhcp);
-
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
-    dhcp_delete_msg(dhcp);
-
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  /* back-off on retries, but to a maximum of 20 seconds */
-  msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-
-/**
- * Rebind with a DHCP server for an existing DHCP lease.
- *
- * @param netif network interface which must rebind with a DHCP server
- */
-static err_t
-dhcp_rebind(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  u16_t msecs;
-  u8_t i;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
-  dhcp_set_state(dhcp, DHCP_STATE_REBINDING);
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
-
-    dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
-    for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
-      dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
-    }
-
-#if LWIP_NETIF_HOSTNAME
-    dhcp_option_hostname(dhcp, netif);
-#endif /* LWIP_NETIF_HOSTNAME */
-
-    dhcp_option_trailer(dhcp);
-
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    /* broadcast to server */
-    udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-
-/**
- * Enter REBOOTING state to verify an existing lease
- *
- * @param netif network interface which must reboot
- */
-static err_t
-dhcp_reboot(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  u16_t msecs;
-  u8_t i;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
-  dhcp_set_state(dhcp, DHCP_STATE_REBOOTING);
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
-    dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED);
-
-    dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
-    dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
-
-    dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
-    for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
-      dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
-    }
-
-    dhcp_option_trailer(dhcp);
-
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    /* broadcast to server */
-    udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
-  } else {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
-  }
-  if (dhcp->tries < 255) {
-    dhcp->tries++;
-  }
-  msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
-  dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
-  return result;
-}
-
-
-/**
- * @ingroup dhcp4
- * Release a DHCP lease (usually called before @ref dhcp_stop).
- *
- * @param netif network interface which must release its lease
- */
-err_t
-dhcp_release(struct netif *netif)
-{
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  err_t result;
-  ip_addr_t server_ip_addr;
-  u8_t is_dhcp_supplied_address;
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
-  if (dhcp == NULL) {
-    return ERR_ARG;
-  }
-  ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
-
-  is_dhcp_supplied_address = dhcp_supplied_address(netif);
-
-  /* idle DHCP client */
-  dhcp_set_state(dhcp, DHCP_STATE_OFF);
-  /* clean old DHCP offer */
-  ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
-  ip4_addr_set_zero(&dhcp->offered_ip_addr);
-  ip4_addr_set_zero(&dhcp->offered_sn_mask);
-  ip4_addr_set_zero(&dhcp->offered_gw_addr);
-#if LWIP_DHCP_BOOTP_FILE
-  ip4_addr_set_zero(&dhcp->offered_si_addr);
-#endif /* LWIP_DHCP_BOOTP_FILE */
-  dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
-  dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0;
-
-  if (!is_dhcp_supplied_address) {
-    /* don't issue release message when address is not dhcp-assigned */
-    return ERR_OK;
-  }
-
-  /* create and initialize the DHCP message header */
-  result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
-  if (result == ERR_OK) {
-    dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
-    dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
-
-    dhcp_option_trailer(dhcp);
-
-    pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
-
-    udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif);
-    dhcp_delete_msg(dhcp);
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
-  } else {
-    /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
-  }
-  /* remove IP address from interface (prevents routing from selecting this interface) */
-  netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
-
-  return result;
-}
-
-/**
- * @ingroup dhcp4
- * Remove the DHCP client from the interface.
- *
- * @param netif The network interface to stop DHCP on
- */
-void
-dhcp_stop(struct netif *netif)
-{
-  struct dhcp *dhcp;
-  LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
-  dhcp = netif_dhcp_data(netif);
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
-  /* netif is DHCP configured? */
-  if (dhcp != NULL) {
-#if LWIP_DHCP_AUTOIP_COOP
-    if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
-      autoip_stop(netif);
-      dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
-    }
-#endif /* LWIP_DHCP_AUTOIP_COOP */
-
-    LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
-    dhcp_set_state(dhcp, DHCP_STATE_OFF);
-
-    if (dhcp->pcb_allocated != 0) {
-      dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
-      dhcp->pcb_allocated = 0;
-    }
-  }
-}
-
-/*
- * Set the DHCP state of a DHCP client.
- *
- * If the state changed, reset the number of tries.
- */
-static void
-dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
-{
-  if (new_state != dhcp->state) {
-    dhcp->state = new_state;
-    dhcp->tries = 0;
-    dhcp->request_timeout = 0;
-  }
-}
-
-/*
- * Concatenate an option type and length field to the outgoing
- * DHCP message.
- *
- */
-static void
-dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
-{
-  LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
-  dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
-  dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
-}
-/*
- * Concatenate a single byte to the outgoing DHCP message.
- *
- */
-static void
-dhcp_option_byte(struct dhcp *dhcp, u8_t value)
-{
-  LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
-  dhcp->msg_out->options[dhcp->options_out_len++] = value;
-}
-
-static void
-dhcp_option_short(struct dhcp *dhcp, u16_t value)
-{
-  LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
-}
-
-static void
-dhcp_option_long(struct dhcp *dhcp, u32_t value)
-{
-  LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
-  dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
-}
-
-#if LWIP_NETIF_HOSTNAME
-static void
-dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif)
-{
-  if (netif->hostname != NULL) {
-    size_t namelen = strlen(netif->hostname);
-    if (namelen > 0) {
-      size_t len;
-      const char *p = netif->hostname;
-      /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME
-         and 1 byte for trailer) */
-      size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3;
-      LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
-      len = LWIP_MIN(namelen, available);
-      LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF);
-      dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len);
-      while (len--) {
-        dhcp_option_byte(dhcp, *p++);
-      }
-    }
-  }
-}
-#endif /* LWIP_NETIF_HOSTNAME */
-
-/**
- * Extract the DHCP message and the DHCP options.
- *
- * Extract the DHCP message and the DHCP options, each into a contiguous
- * piece of memory. As a DHCP message is variable sized by its options,
- * and also allows overriding some fields for options, the easy approach
- * is to first unfold the options into a contiguous piece of memory, and
- * use that further on.
- *
- */
-static err_t
-dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p)
-{
-  u8_t *options;
-  u16_t offset;
-  u16_t offset_max;
-  u16_t options_idx;
-  u16_t options_idx_max;
-  struct pbuf *q;
-  int parse_file_as_options = 0;
-  int parse_sname_as_options = 0;
-
-  /* clear received options */
-  dhcp_clear_all_options(dhcp);
-  /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
-  if (p->len < DHCP_SNAME_OFS) {
-    return ERR_BUF;
-  }
-  dhcp->msg_in = (struct dhcp_msg *)p->payload;
-#if LWIP_DHCP_BOOTP_FILE
-  /* clear boot file name */
-  dhcp->boot_file_name[0] = 0;
-#endif /* LWIP_DHCP_BOOTP_FILE */
-
-  /* parse options */
-
-  /* start with options field */
-  options_idx = DHCP_OPTIONS_OFS;
-  /* parse options to the end of the received packet */
-  options_idx_max = p->tot_len;
-again:
-  q = p;
-  while ((q != NULL) && (options_idx >= q->len)) {
-    options_idx -= q->len;
-    options_idx_max -= q->len;
-    q = q->next;
-  }
-  if (q == NULL) {
-    return ERR_BUF;
-  }
-  offset = options_idx;
-  offset_max = options_idx_max;
-  options = (u8_t*)q->payload;
-  /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
-  while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
-    u8_t op = options[offset];
-    u8_t len;
-    u8_t decode_len = 0;
-    int decode_idx = -1;
-    u16_t val_offset = offset + 2;
-    /* len byte might be in the next pbuf */
-    if ((offset + 1) < q->len) {
-      len = options[offset + 1];
-    } else {
-      len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
-    }
-    /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
-    decode_len = len;
-    switch(op) {
-      /* case(DHCP_OPTION_END): handled above */
-      case(DHCP_OPTION_PAD):
-        /* special option: no len encoded */
-        decode_len = len = 0;
-        /* will be increased below */
-        offset--;
-        break;
-      case(DHCP_OPTION_SUBNET_MASK):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
-        break;
-      case(DHCP_OPTION_ROUTER):
-        decode_len = 4; /* only copy the first given router */
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_ROUTER;
-        break;
-      case(DHCP_OPTION_DNS_SERVER):
-        /* special case: there might be more than one server */
-        LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
-        /* limit number of DNS servers */
-        decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
-        break;
-      case(DHCP_OPTION_LEASE_TIME):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
-        break;
-#if LWIP_DHCP_GET_NTP_SRV
-      case(DHCP_OPTION_NTP):
-        /* special case: there might be more than one server */
-        LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
-        /* limit number of NTP servers */
-        decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
-        break;
-#endif /* LWIP_DHCP_GET_NTP_SRV*/
-      case(DHCP_OPTION_OVERLOAD):
-        LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_OVERLOAD;
-        break;
-      case(DHCP_OPTION_MESSAGE_TYPE):
-        LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
-        break;
-      case(DHCP_OPTION_SERVER_ID):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_SERVER_ID;
-        break;
-      case(DHCP_OPTION_T1):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_T1;
-        break;
-      case(DHCP_OPTION_T2):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
-        decode_idx = DHCP_OPTION_IDX_T2;
-        break;
-      default:
-        decode_len = 0;
-        LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op));
-        break;
-    }
-    offset += len + 2;
-    if (decode_len > 0) {
-      u32_t value = 0;
-      u16_t copy_len;
-decode_next:
-      LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
-      if (!dhcp_option_given(dhcp, decode_idx)) {
-        copy_len = LWIP_MIN(decode_len, 4);
-        if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) {
-          return ERR_BUF;
-        }
-        if (decode_len > 4) {
-          /* decode more than one u32_t */
-          LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
-          dhcp_got_option(dhcp, decode_idx);
-          dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
-          decode_len -= 4;
-          val_offset += 4;
-          decode_idx++;
-          goto decode_next;
-        } else if (decode_len == 4) {
-          value = lwip_ntohl(value);
-        } else {
-          LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
-          value = ((u8_t*)&value)[0];
-        }
-        dhcp_got_option(dhcp, decode_idx);
-        dhcp_set_option_value(dhcp, decode_idx, value);
-      }
-    }
-    if (offset >= q->len) {
-      offset -= q->len;
-      offset_max -= q->len;
-      if ((offset < offset_max) && offset_max) {
-        q = q->next;
-        LWIP_ASSERT("next pbuf was null", q);
-        options = (u8_t*)q->payload;
-      } else {
-        /* We've run out of bytes, probably no end marker. Don't proceed. */
-        break;
-      }
-    }
-  }
-  /* is this an overloaded message? */
-  if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
-    u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
-    dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
-    if (overload == DHCP_OVERLOAD_FILE) {
-      parse_file_as_options = 1;
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
-    } else if (overload == DHCP_OVERLOAD_SNAME) {
-      parse_sname_as_options = 1;
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
-    } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
-      parse_sname_as_options = 1;
-      parse_file_as_options = 1;
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
-    } else {
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
-    }
-#if LWIP_DHCP_BOOTP_FILE
-    if (!parse_file_as_options) {
-      /* only do this for ACK messages */
-      if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
-        (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
-      /* copy bootp file name, don't care for sname (server hostname) */
-      if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) {
-        return ERR_BUF;
-      }
-      /* make sure the string is really NULL-terminated */
-      dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
-    }
-#endif /* LWIP_DHCP_BOOTP_FILE */
-  }
-  if (parse_file_as_options) {
-    /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
-    parse_file_as_options = 0;
-    options_idx = DHCP_FILE_OFS;
-    options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
-    goto again;
-  } else if (parse_sname_as_options) {
-    parse_sname_as_options = 0;
-    options_idx = DHCP_SNAME_OFS;
-    options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
-    goto again;
-  }
-  return ERR_OK;
-}
-
-/**
- * If an incoming DHCP message is in response to us, then trigger the state machine
- */
-static void
-dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
-{
-  struct netif *netif = ip_current_input_netif();
-  struct dhcp *dhcp = netif_dhcp_data(netif);
-  struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
-  u8_t msg_type;
-  u8_t i;
-
-  LWIP_UNUSED_ARG(arg);
-
-  /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */
-  if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) {
-    goto free_pbuf_and_return;
-  }
-
-  LWIP_ASSERT("invalid server address type", IP_IS_V4(addr));
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
-    ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port));
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
-  /* prevent warnings about unused arguments */
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_UNUSED_ARG(addr);
-  LWIP_UNUSED_ARG(port);
-
-  LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
-
-  if (p->len < DHCP_MIN_REPLY_LEN) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
-    goto free_pbuf_and_return;
-  }
-
-  if (reply_msg->op != DHCP_BOOTREPLY) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
-    goto free_pbuf_and_return;
-  }
-  /* iterate through hardware address and match against DHCP message */
-  for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) {
-    if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
-      LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
-        ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
-        (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
-      goto free_pbuf_and_return;
-    }
-  }
-  /* match transaction ID against what we expected */
-  if (lwip_ntohl(reply_msg->xid) != dhcp->xid) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
-      ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid));
-    goto free_pbuf_and_return;
-  }
-  /* option fields could be unfold? */
-  if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
-      ("problem unfolding DHCP message - too short on memory?\n"));
-    goto free_pbuf_and_return;
-  }
-
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
-  /* obtain pointer to DHCP message type */
-  if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
-    goto free_pbuf_and_return;
-  }
-
-  /* read DHCP message type */
-  msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
-  /* message type is DHCP ACK? */
-  if (msg_type == DHCP_ACK) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
-    /* in requesting state? */
-    if (dhcp->state == DHCP_STATE_REQUESTING) {
-      dhcp_handle_ack(netif);
-#if DHCP_DOES_ARP_CHECK
-      if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
-        /* check if the acknowledged lease address is already in use */
-        dhcp_check(netif);
-      } else {
-        /* bind interface to the acknowledged lease address */
-        dhcp_bind(netif);
-      }
-#else
-      /* bind interface to the acknowledged lease address */
-      dhcp_bind(netif);
-#endif
-    }
-    /* already bound to the given lease address? */
-    else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) ||
-             (dhcp->state == DHCP_STATE_RENEWING)) {
-      dhcp_handle_ack(netif);
-      dhcp_bind(netif);
-    }
-  }
-  /* received a DHCP_NAK in appropriate state? */
-  else if ((msg_type == DHCP_NAK) &&
-    ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) ||
-     (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING  ))) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
-    dhcp_handle_nak(netif);
-  }
-  /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */
-  else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n"));
-    dhcp->request_timeout = 0;
-    /* remember offered lease */
-    dhcp_handle_offer(netif);
-  }
-
-free_pbuf_and_return:
-  if (dhcp != NULL) {
-    dhcp->msg_in = NULL;
-  }
-  pbuf_free(p);
-}
-
-/**
- * Create a DHCP request, fill in common headers
- *
- * @param netif the netif under DHCP control
- * @param dhcp dhcp control struct
- * @param message_type message type of the request
- */
-static err_t
-dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
-{
-  u16_t i;
-#ifndef DHCP_GLOBAL_XID
-  /** default global transaction identifier starting value (easy to match
-   *  with a packet analyser). We simply increment for each new request.
-   *  Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
-   *  at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
-#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
-  static u32_t xid;
-#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
-  static u32_t xid = 0xABCD0000;
-#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
-#else
-  if (!xid_initialised) {
-    xid = DHCP_GLOBAL_XID;
-    xid_initialised = !xid_initialised;
-  }
-#endif
-  LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;);
-  LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
-  LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
-  LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
-  dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
-  if (dhcp->p_out == NULL) {
-    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
-      ("dhcp_create_msg(): could not allocate pbuf\n"));
-    return ERR_MEM;
-  }
-  LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
-           (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
-
-  /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
-  if (message_type != DHCP_REQUEST) {
-    /* reuse transaction identifier in retransmissions */
-    if (dhcp->tries == 0) {
-#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
-      xid = LWIP_RAND();
-#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
-      xid++;
-#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
-    }
-    dhcp->xid = xid;
-  }
-  LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
-              ("transaction id xid(%"X32_F")\n", xid));
-
-  dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
-
-  dhcp->msg_out->op = DHCP_BOOTREQUEST;
-  /* @todo: make link layer independent */
-  dhcp->msg_out->htype = DHCP_HTYPE_ETH;
-  dhcp->msg_out->hlen = netif->hwaddr_len;
-  dhcp->msg_out->hops = 0;
-  dhcp->msg_out->xid = lwip_htonl(dhcp->xid);
-  dhcp->msg_out->secs = 0;
-  /* we don't need the broadcast flag since we can receive unicast traffic
-     before being fully configured! */
-  dhcp->msg_out->flags = 0;
-  ip4_addr_set_zero(&dhcp->msg_out->ciaddr);
-  /* set ciaddr to netif->ip_addr based on message_type and state */
-  if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) ||
-      ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */
-       ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) {
-    ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif));
-  }
-  ip4_addr_set_zero(&dhcp->msg_out->yiaddr);
-  ip4_addr_set_zero(&dhcp->msg_out->siaddr);
-  ip4_addr_set_zero(&dhcp->msg_out->giaddr);
-  for (i = 0; i < DHCP_CHADDR_LEN; i++) {
-    /* copy netif hardware address, pad with zeroes */
-    dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/;
-  }
-  for (i = 0; i < DHCP_SNAME_LEN; i++) {
-    dhcp->msg_out->sname[i] = 0;
-  }
-  for (i = 0; i < DHCP_FILE_LEN; i++) {
-    dhcp->msg_out->file[i] = 0;
-  }
-  dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
-  dhcp->options_out_len = 0;
-  /* fill options field with an incrementing array (for debugging purposes) */
-  for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
-    dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
-  }
-  /* Add option MESSAGE_TYPE */
-  dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
-  dhcp_option_byte(dhcp, message_type);
-  return ERR_OK;
-}
-
-/**
- * Free previously allocated memory used to send a DHCP request.
- *
- * @param dhcp the dhcp struct to free the request from
- */
-static void
-dhcp_delete_msg(struct dhcp *dhcp)
-{
-  LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;);
-  LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
-  LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
-  if (dhcp->p_out != NULL) {
-    pbuf_free(dhcp->p_out);
-  }
-  dhcp->p_out = NULL;
-  dhcp->msg_out = NULL;
-}
-
-/**
- * Add a DHCP message trailer
- *
- * Adds the END option to the DHCP message, and if
- * necessary, up to three padding bytes.
- *
- * @param dhcp DHCP state structure
- */
-static void
-dhcp_option_trailer(struct dhcp *dhcp)
-{
-  LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
-  LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
-  LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
-  dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
-  /* packet is too small, or not 4 byte aligned? */
-  while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) &&
-         (dhcp->options_out_len < DHCP_OPTIONS_LEN)) {
-    /* add a fill/padding byte */
-    dhcp->msg_out->options[dhcp->options_out_len++] = 0;
-  }
-}
-
-/** check if DHCP supplied netif->ip_addr
- *
- * @param netif the netif to check
- * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING),
- *         0 otherwise
- */
-u8_t
-dhcp_supplied_address(const struct netif *netif)
-{
-  if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
-    struct dhcp* dhcp = netif_dhcp_data(netif);
-    return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING);
-  }
-  return 0;
-}
-
-#endif /* LWIP_IPV4 && LWIP_DHCP */

+ 0 - 1224
components/net/lwip-2.0.0/src/core/ipv4/etharp.c

@@ -1,1224 +0,0 @@
-/**
- * @file
- * Address Resolution Protocol module for IP over Ethernet
- *
- * Functionally, ARP is divided into two parts. The first maps an IP address
- * to a physical address when sending a packet, and the second part answers
- * requests from other machines for our physical address.
- *
- * This implementation complies with RFC 826 (Ethernet ARP). It supports
- * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
- * if an interface calls etharp_gratuitous(our_netif) upon address change.
- */
-
-/*
- * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
- * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_ARP || LWIP_ETHERNET
-
-#include "lwip/etharp.h"
-#include "lwip/stats.h"
-#include "lwip/snmp.h"
-#include "lwip/dhcp.h"
-#include "lwip/autoip.h"
-#include "netif/ethernet.h"
-
-#include <string.h>
-
-#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */
-
-/** Re-request a used ARP entry 1 minute before it would expire to prevent
- *  breaking a steadily used connection because the ARP entry timed out. */
-#define ARP_AGE_REREQUEST_USED_UNICAST   (ARP_MAXAGE - 30)
-#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15)
-
-/** the time an ARP entry stays pending after first request,
- *  for ARP_TMR_INTERVAL = 1000, this is
- *  10 seconds.
- *
- *  @internal Keep this number at least 2, otherwise it might
- *  run out instantly if the timeout occurs directly after a request.
- */
-#define ARP_MAXPENDING 5
-
-/** ARP states */
-enum etharp_state {
-  ETHARP_STATE_EMPTY = 0,
-  ETHARP_STATE_PENDING,
-  ETHARP_STATE_STABLE,
-  ETHARP_STATE_STABLE_REREQUESTING_1,
-  ETHARP_STATE_STABLE_REREQUESTING_2
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-  ,ETHARP_STATE_STATIC
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-};
-
-struct etharp_entry {
-#if ARP_QUEUEING
-  /** Pointer to queue of pending outgoing packets on this ARP entry. */
-  struct etharp_q_entry *q;
-#else /* ARP_QUEUEING */
-  /** Pointer to a single pending outgoing packet on this ARP entry. */
-  struct pbuf *q;
-#endif /* ARP_QUEUEING */
-  ip4_addr_t ipaddr;
-  struct netif *netif;
-  struct eth_addr ethaddr;
-  u16_t ctime;
-  u8_t state;
-};
-
-static struct etharp_entry arp_table[ARP_TABLE_SIZE];
-
-#if !LWIP_NETIF_HWADDRHINT
-static u8_t etharp_cached_entry;
-#endif /* !LWIP_NETIF_HWADDRHINT */
-
-/** Try hard to create a new entry - we want the IP address to appear in
-    the cache (even if this means removing an active entry or so). */
-#define ETHARP_FLAG_TRY_HARD     1
-#define ETHARP_FLAG_FIND_ONLY    2
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-#define ETHARP_FLAG_STATIC_ENTRY 4
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-
-#if LWIP_NETIF_HWADDRHINT
-#define ETHARP_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
-                                      *((netif)->addr_hint) = (hint);
-#else /* LWIP_NETIF_HWADDRHINT */
-#define ETHARP_SET_HINT(netif, hint)  (etharp_cached_entry = (hint))
-#endif /* LWIP_NETIF_HWADDRHINT */
-
-
-/* Some checks, instead of etharp_init(): */
-#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
-  #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
-#endif
-
-
-static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr);
-
-
-#if ARP_QUEUEING
-/**
- * Free a complete queue of etharp entries
- *
- * @param q a qeueue of etharp_q_entry's to free
- */
-static void
-free_etharp_q(struct etharp_q_entry *q)
-{
-  struct etharp_q_entry *r;
-  LWIP_ASSERT("q != NULL", q != NULL);
-  LWIP_ASSERT("q->p != NULL", q->p != NULL);
-  while (q) {
-    r = q;
-    q = q->next;
-    LWIP_ASSERT("r->p != NULL", (r->p != NULL));
-    pbuf_free(r->p);
-    memp_free(MEMP_ARP_QUEUE, r);
-  }
-}
-#else /* ARP_QUEUEING */
-
-/** Compatibility define: free the queued pbuf */
-#define free_etharp_q(q) pbuf_free(q)
-
-#endif /* ARP_QUEUEING */
-
-/** Clean up ARP table entries */
-static void
-etharp_free_entry(int i)
-{
-  /* remove from SNMP ARP index tree */
-  mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr);
-  /* and empty packet queue */
-  if (arp_table[i].q != NULL) {
-    /* remove all queued packets */
-    LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
-    free_etharp_q(arp_table[i].q);
-    arp_table[i].q = NULL;
-  }
-  /* recycle entry for re-use */
-  arp_table[i].state = ETHARP_STATE_EMPTY;
-#ifdef LWIP_DEBUG
-  /* for debugging, clean out the complete entry */
-  arp_table[i].ctime = 0;
-  arp_table[i].netif = NULL;
-  ip4_addr_set_zero(&arp_table[i].ipaddr);
-  arp_table[i].ethaddr = ethzero;
-#endif /* LWIP_DEBUG */
-}
-
-/**
- * Clears expired entries in the ARP table.
- *
- * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second),
- * in order to expire entries in the ARP table.
- */
-void
-etharp_tmr(void)
-{
-  u8_t i;
-
-  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
-  /* remove expired entries from the ARP table */
-  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
-    u8_t state = arp_table[i].state;
-    if (state != ETHARP_STATE_EMPTY
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-      && (state != ETHARP_STATE_STATIC)
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-      ) {
-      arp_table[i].ctime++;
-      if ((arp_table[i].ctime >= ARP_MAXAGE) ||
-          ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
-           (arp_table[i].ctime >= ARP_MAXPENDING))) {
-        /* pending or stable entry has become old! */
-        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
-             arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
-        /* clean up entries that have just been expired */
-        etharp_free_entry(i);
-      } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
-        /* Don't send more than one request every 2 seconds. */
-        arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2;
-      } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) {
-        /* Reset state to stable, so that the next transmitted packet will
-           re-send an ARP request. */
-        arp_table[i].state = ETHARP_STATE_STABLE;
-      } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
-        /* still pending, resend an ARP query */
-        etharp_request(arp_table[i].netif, &arp_table[i].ipaddr);
-      }
-    }
-  }
-}
-
-/**
- * Search the ARP table for a matching or new entry.
- *
- * If an IP address is given, return a pending or stable ARP entry that matches
- * the address. If no match is found, create a new entry with this address set,
- * but in state ETHARP_EMPTY. The caller must check and possibly change the
- * state of the returned entry.
- *
- * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
- *
- * In all cases, attempt to create new entries from an empty entry. If no
- * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle
- * old entries. Heuristic choose the least important entry for recycling.
- *
- * @param ipaddr IP address to find in ARP cache, or to add if not found.
- * @param flags See @ref etharp_state
- * @param netif netif related to this address (used for NETIF_HWADDRHINT)
- *
- * @return The ARP entry index that matched or is created, ERR_MEM if no
- * entry is found or could be recycled.
- */
-static s8_t
-etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif)
-{
-  s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
-  s8_t empty = ARP_TABLE_SIZE;
-  u8_t i = 0;
-  /* oldest entry with packets on queue */
-  s8_t old_queue = ARP_TABLE_SIZE;
-  /* its age */
-  u16_t age_queue = 0, age_pending = 0, age_stable = 0;
-
-  LWIP_UNUSED_ARG(netif);
-
-  /**
-   * a) do a search through the cache, remember candidates
-   * b) select candidate entry
-   * c) create new entry
-   */
-
-  /* a) in a single search sweep, do all of this
-   * 1) remember the first empty entry (if any)
-   * 2) remember the oldest stable entry (if any)
-   * 3) remember the oldest pending entry without queued packets (if any)
-   * 4) remember the oldest pending entry with queued packets (if any)
-   * 5) search for a matching IP entry, either pending or stable
-   *    until 5 matches, or all entries are searched for.
-   */
-
-  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
-    u8_t state = arp_table[i].state;
-    /* no empty entry found yet and now we do find one? */
-    if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
-      LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i));
-      /* remember first empty entry */
-      empty = i;
-    } else if (state != ETHARP_STATE_EMPTY) {
-      LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
-        state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
-      /* if given, does IP address match IP address in ARP entry? */
-      if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr)
-#if ETHARP_TABLE_MATCH_NETIF
-          && ((netif == NULL) || (netif == arp_table[i].netif))
-#endif /* ETHARP_TABLE_MATCH_NETIF */
-        ) {
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i));
-        /* found exact IP address match, simply bail out */
-        return i;
-      }
-      /* pending entry? */
-      if (state == ETHARP_STATE_PENDING) {
-        /* pending with queued packets? */
-        if (arp_table[i].q != NULL) {
-          if (arp_table[i].ctime >= age_queue) {
-            old_queue = i;
-            age_queue = arp_table[i].ctime;
-          }
-        } else
-        /* pending without queued packets? */
-        {
-          if (arp_table[i].ctime >= age_pending) {
-            old_pending = i;
-            age_pending = arp_table[i].ctime;
-          }
-        }
-      /* stable entry? */
-      } else if (state >= ETHARP_STATE_STABLE) {
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-        /* don't record old_stable for static entries since they never expire */
-        if (state < ETHARP_STATE_STATIC)
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-        {
-          /* remember entry with oldest stable entry in oldest, its age in maxtime */
-          if (arp_table[i].ctime >= age_stable) {
-            old_stable = i;
-            age_stable = arp_table[i].ctime;
-          }
-        }
-      }
-    }
-  }
-  /* { we have no match } => try to create a new entry */
-
-  /* don't create new entry, only search? */
-  if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
-      /* or no empty entry found and not allowed to recycle? */
-      ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
-    return (s8_t)ERR_MEM;
-  }
-
-  /* b) choose the least destructive entry to recycle:
-   * 1) empty entry
-   * 2) oldest stable entry
-   * 3) oldest pending entry without queued packets
-   * 4) oldest pending entry with queued packets
-   *
-   * { ETHARP_FLAG_TRY_HARD is set at this point }
-   */
-
-  /* 1) empty entry available? */
-  if (empty < ARP_TABLE_SIZE) {
-    i = empty;
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
-  } else {
-    /* 2) found recyclable stable entry? */
-    if (old_stable < ARP_TABLE_SIZE) {
-      /* recycle oldest stable*/
-      i = old_stable;
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
-      /* no queued packets should exist on stable entries */
-      LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
-    /* 3) found recyclable pending entry without queued packets? */
-    } else if (old_pending < ARP_TABLE_SIZE) {
-      /* recycle oldest pending */
-      i = old_pending;
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
-    /* 4) found recyclable pending entry with queued packets? */
-    } else if (old_queue < ARP_TABLE_SIZE) {
-      /* recycle oldest pending (queued packets are free in etharp_free_entry) */
-      i = old_queue;
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
-      /* no empty or recyclable entries found */
-    } else {
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n"));
-      return (s8_t)ERR_MEM;
-    }
-
-    /* { empty or recyclable entry found } */
-    LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
-    etharp_free_entry(i);
-  }
-
-  LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
-  LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
-    arp_table[i].state == ETHARP_STATE_EMPTY);
-
-  /* IP address given? */
-  if (ipaddr != NULL) {
-    /* set IP address */
-    ip4_addr_copy(arp_table[i].ipaddr, *ipaddr);
-  }
-  arp_table[i].ctime = 0;
-#if ETHARP_TABLE_MATCH_NETIF
-  arp_table[i].netif = netif;
-#endif /* ETHARP_TABLE_MATCH_NETIF*/
-  return (err_t)i;
-}
-
-/**
- * Update (or insert) a IP/MAC address pair in the ARP cache.
- *
- * If a pending entry is resolved, any queued packets will be sent
- * at this point.
- *
- * @param netif netif related to this entry (used for NETIF_ADDRHINT)
- * @param ipaddr IP address of the inserted ARP entry.
- * @param ethaddr Ethernet address of the inserted ARP entry.
- * @param flags See @ref etharp_state
- *
- * @return
- * - ERR_OK Successfully updated ARP cache.
- * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set.
- * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
- *
- * @see pbuf_free()
- */
-static err_t
-etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
-{
-  s8_t i;
-  LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN);
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
-    ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
-    (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
-    (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
-  /* non-unicast address? */
-  if (ip4_addr_isany(ipaddr) ||
-      ip4_addr_isbroadcast(ipaddr, netif) ||
-      ip4_addr_ismulticast(ipaddr)) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
-    return ERR_ARG;
-  }
-  /* find or create ARP entry */
-  i = etharp_find_entry(ipaddr, flags, netif);
-  /* bail out if no entry could be found */
-  if (i < 0) {
-    return (err_t)i;
-  }
-
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-  if (flags & ETHARP_FLAG_STATIC_ENTRY) {
-    /* record static type */
-    arp_table[i].state = ETHARP_STATE_STATIC;
-  } else if (arp_table[i].state == ETHARP_STATE_STATIC) {
-    /* found entry is a static type, don't overwrite it */
-    return ERR_VAL;
-  } else
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-  {
-    /* mark it stable */
-    arp_table[i].state = ETHARP_STATE_STABLE;
-  }
-
-  /* record network interface */
-  arp_table[i].netif = netif;
-  /* insert in SNMP ARP index tree */
-  mib2_add_arp_entry(netif, &arp_table[i].ipaddr);
-
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
-  /* update address */
-  ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
-  /* reset time stamp */
-  arp_table[i].ctime = 0;
-  /* this is where we will send out queued packets! */
-#if ARP_QUEUEING
-  while (arp_table[i].q != NULL) {
-    struct pbuf *p;
-    /* remember remainder of queue */
-    struct etharp_q_entry *q = arp_table[i].q;
-    /* pop first item off the queue */
-    arp_table[i].q = q->next;
-    /* get the packet pointer */
-    p = q->p;
-    /* now queue entry can be freed */
-    memp_free(MEMP_ARP_QUEUE, q);
-#else /* ARP_QUEUEING */
-  if (arp_table[i].q != NULL) {
-    struct pbuf *p = arp_table[i].q;
-    arp_table[i].q = NULL;
-#endif /* ARP_QUEUEING */
-    /* send the queued IP packet */
-    ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP);
-    /* free the queued IP packet */
-    pbuf_free(p);
-  }
-  return ERR_OK;
-}
-
-#if ETHARP_SUPPORT_STATIC_ENTRIES
-/** Add a new static entry to the ARP table. If an entry exists for the
- * specified IP address, this entry is overwritten.
- * If packets are queued for the specified IP address, they are sent out.
- *
- * @param ipaddr IP address for the new static entry
- * @param ethaddr ethernet address for the new static entry
- * @return See return values of etharp_add_static_entry
- */
-err_t
-etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr)
-{
-  struct netif *netif;
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
-    ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
-    (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
-    (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
-
-  netif = ip4_route(ipaddr);
-  if (netif == NULL) {
-    return ERR_RTE;
-  }
-
-  return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
-}
-
-/** Remove a static entry from the ARP table previously added with a call to
- * etharp_add_static_entry.
- *
- * @param ipaddr IP address of the static entry to remove
- * @return ERR_OK: entry removed
- *         ERR_MEM: entry wasn't found
- *         ERR_ARG: entry wasn't a static entry but a dynamic one
- */
-err_t
-etharp_remove_static_entry(const ip4_addr_t *ipaddr)
-{
-  s8_t i;
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-    ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
-
-  /* find or create ARP entry */
-  i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL);
-  /* bail out if no entry could be found */
-  if (i < 0) {
-    return (err_t)i;
-  }
-
-  if (arp_table[i].state != ETHARP_STATE_STATIC) {
-    /* entry wasn't a static entry, cannot remove it */
-    return ERR_ARG;
-  }
-  /* entry found, free it */
-  etharp_free_entry(i);
-  return ERR_OK;
-}
-#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
-
-/**
- * Remove all ARP table entries of the specified netif.
- *
- * @param netif points to a network interface
- */
-void
-etharp_cleanup_netif(struct netif *netif)
-{
-  u8_t i;
-
-  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
-    u8_t state = arp_table[i].state;
-    if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) {
-      etharp_free_entry(i);
-    }
-  }
-}
-
-/**
- * Finds (stable) ethernet/IP address pair from ARP table
- * using interface and IP address index.
- * @note the addresses in the ARP table are in network order!
- *
- * @param netif points to interface index
- * @param ipaddr points to the (network order) IP address index
- * @param eth_ret points to return pointer
- * @param ip_ret points to return pointer
- * @return table index if found, -1 otherwise
- */
-s8_t
-etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr,
-         struct eth_addr **eth_ret, const ip4_addr_t **ip_ret)
-{
-  s8_t i;
-
-  LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
-    eth_ret != NULL && ip_ret != NULL);
-
-  LWIP_UNUSED_ARG(netif);
-
-  i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif);
-  if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
-      *eth_ret = &arp_table[i].ethaddr;
-      *ip_ret = &arp_table[i].ipaddr;
-      return i;
-  }
-  return -1;
-}
-
-/**
- * Possibility to iterate over stable ARP table entries
- *
- * @param i entry number, 0 to ARP_TABLE_SIZE
- * @param ipaddr return value: IP address
- * @param netif return value: points to interface
- * @param eth_ret return value: ETH address
- * @return 1 on valid index, 0 otherwise
- */
-u8_t
-etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret)
-{
-  LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-  LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL);
-
-  if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
-    *ipaddr  = &arp_table[i].ipaddr;
-    *netif   = arp_table[i].netif;
-    *eth_ret = &arp_table[i].ethaddr;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-/**
- * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
- * send out queued IP packets. Updates cache with snooped address pairs.
- *
- * Should be called for incoming ARP packets. The pbuf in the argument
- * is freed by this function.
- *
- * @param p The ARP packet that arrived on netif. Is freed by this function.
- * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
- *
- * @see pbuf_free()
- */
-void
-etharp_input(struct pbuf *p, struct netif *netif)
-{
-  struct etharp_hdr *hdr;
-  /* these are aligned properly, whereas the ARP header fields might not be */
-  ip4_addr_t sipaddr, dipaddr;
-  u8_t for_us;
-
-  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
-
-  hdr = (struct etharp_hdr *)p->payload;
-
-  /* RFC 826 "Packet Reception": */
-  if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
-      (hdr->hwlen != ETH_HWADDR_LEN) ||
-      (hdr->protolen != sizeof(ip4_addr_t)) ||
-      (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
-      ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
-      hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
-    ETHARP_STATS_INC(etharp.proterr);
-    ETHARP_STATS_INC(etharp.drop);
-    pbuf_free(p);
-    return;
-  }
-  ETHARP_STATS_INC(etharp.recv);
-
-#if LWIP_AUTOIP
-  /* We have to check if a host already has configured our random
-   * created link local address and continuously check if there is
-   * a host with this IP-address so we can detect collisions */
-  autoip_arp_reply(netif, hdr);
-#endif /* LWIP_AUTOIP */
-
-  /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
-   * structure packing (not using structure copy which breaks strict-aliasing rules). */
-  IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
-  IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
-
-  /* this interface is not configured? */
-  if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
-    for_us = 0;
-  } else {
-    /* ARP packet directed to us? */
-    for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif));
-  }
-
-  /* ARP message directed to us?
-      -> add IP address in ARP cache; assume requester wants to talk to us,
-         can result in directly sending the queued packets for this host.
-     ARP message not directed to us?
-      ->  update the source IP address in the cache, if present */
-  etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
-                   for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
-
-  /* now act on the message itself */
-  switch (hdr->opcode) {
-  /* ARP request? */
-  case PP_HTONS(ARP_REQUEST):
-    /* ARP request. If it asked for our address, we send out a
-     * reply. In any case, we time-stamp any existing ARP entry,
-     * and possibly send out an IP packet that was queued on it. */
-
-    LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
-    /* ARP request for our address? */
-    if (for_us) {
-
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n"));
-      /* Re-use pbuf to send ARP reply.
-         Since we are re-using an existing pbuf, we can't call etharp_raw since
-         that would allocate a new pbuf. */
-      hdr->opcode = lwip_htons(ARP_REPLY);
-
-      IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
-      IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif));
-
-      LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
-                  (netif->hwaddr_len == ETH_HWADDR_LEN));
-
-      /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
-         are already correct, we tested that before */
-
-      ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
-      ETHADDR16_COPY(&hdr->shwaddr, netif->hwaddr);
-
-      /* return ARP reply */
-#if LWIP_AUTOIP
-      /* If we are using Link-Local, all ARP packets that contain a Link-Local
-       * 'sender IP address' MUST be sent using link-layer broadcast instead of
-       * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
-      if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
-        ethernet_output(netif, p, &hdr->shwaddr, &ethbroadcast, ETHTYPE_ARP);
-      } else
-#endif /* LWIP_AUTOIP */
-      {
-        ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP);
-      }
-
-    /* we are not configured? */
-    } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
-      /* { for_us == 0 and netif->ip_addr.addr == 0 } */
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
-    /* request was not directed to us */
-    } else {
-      /* { for_us == 0 and netif->ip_addr.addr != 0 } */
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
-    }
-    break;
-  case PP_HTONS(ARP_REPLY):
-    /* ARP reply. We already updated the ARP cache earlier. */
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
-#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
-    /* DHCP wants to know about ARP replies from any host with an
-     * IP address also offered to us by the DHCP server. We do not
-     * want to take a duplicate IP address on a single network.
-     * @todo How should we handle redundant (fail-over) interfaces? */
-    dhcp_arp_reply(netif, &sipaddr);
-#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
-    break;
-  default:
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
-    ETHARP_STATS_INC(etharp.err);
-    break;
-  }
-  /* free ARP packet */
-  pbuf_free(p);
-}
-
-/** Just a small helper function that sends a pbuf to an ethernet address
- * in the arp_table specified by the index 'arp_idx'.
- */
-static err_t
-etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
-{
-  LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
-              arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
-  /* if arp table entry is about to expire: re-request it,
-     but only if its state is ETHARP_STATE_STABLE to prevent flooding the
-     network with ARP requests if this address is used frequently. */
-  if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) {
-    if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) {
-      /* issue a standard request using broadcast */
-      if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) {
-        arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
-      }
-    } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) {
-      /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */
-      if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) {
-        arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
-      }
-    }
-  }
-
-  return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP);
-}
-
-/**
- * Resolve and fill-in Ethernet address header for outgoing IP packet.
- *
- * For IP multicast and broadcast, corresponding Ethernet addresses
- * are selected and the packet is transmitted on the link.
- *
- * For unicast addresses, the packet is submitted to etharp_query(). In
- * case the IP address is outside the local network, the IP address of
- * the gateway is used.
- *
- * @param netif The lwIP network interface which the IP packet will be sent on.
- * @param q The pbuf(s) containing the IP packet to be sent.
- * @param ipaddr The IP address of the packet destination.
- *
- * @return
- * - ERR_RTE No route to destination (no gateway to external networks),
- * or the return type of either etharp_query() or ethernet_output().
- */
-err_t
-etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
-{
-  const struct eth_addr *dest;
-  struct eth_addr mcastaddr;
-  const ip4_addr_t *dst_addr = ipaddr;
-
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-  LWIP_ASSERT("q != NULL", q != NULL);
-  LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
-
-  /* Determine on destination hardware address. Broadcasts and multicasts
-   * are special, other IP addresses are looked up in the ARP table. */
-
-  /* broadcast destination IP address? */
-  if (ip4_addr_isbroadcast(ipaddr, netif)) {
-    /* broadcast on Ethernet also */
-    dest = (const struct eth_addr *)&ethbroadcast;
-  /* multicast destination IP address? */
-  } else if (ip4_addr_ismulticast(ipaddr)) {
-    /* Hash IP multicast address to MAC address.*/
-    mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0;
-    mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1;
-    mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2;
-    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
-    mcastaddr.addr[4] = ip4_addr3(ipaddr);
-    mcastaddr.addr[5] = ip4_addr4(ipaddr);
-    /* destination Ethernet address is multicast */
-    dest = &mcastaddr;
-  /* unicast destination IP address? */
-  } else {
-    s8_t i;
-    /* outside local network? if so, this can neither be a global broadcast nor
-       a subnet broadcast. */
-    if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
-        !ip4_addr_islinklocal(ipaddr)) {
-#if LWIP_AUTOIP
-      struct ip_hdr *iphdr = (struct ip_hdr*)(size_t)q->payload;
-      /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
-         a link-local source address must always be "directly to its destination
-         on the same physical link. The host MUST NOT send the packet to any
-         router for forwarding". */
-      if (!ip4_addr_islinklocal(&iphdr->src))
-#endif /* LWIP_AUTOIP */
-      {
-#ifdef LWIP_HOOK_ETHARP_GET_GW
-        /* For advanced routing, a single default gateway might not be enough, so get
-           the IP address of the gateway to handle the current destination address. */
-        dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr);
-        if (dst_addr == NULL)
-#endif /* LWIP_HOOK_ETHARP_GET_GW */
-        {
-          /* interface has default gateway? */
-          if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) {
-            /* send to hardware address of default gateway IP address */
-            dst_addr = netif_ip4_gw(netif);
-          /* no default gateway available */
-          } else {
-            /* no route to destination error (default gateway missing) */
-            return ERR_RTE;
-          }
-        }
-      }
-    }
-#if LWIP_NETIF_HWADDRHINT
-    if (netif->addr_hint != NULL) {
-      /* per-pcb cached entry was given */
-      u8_t etharp_cached_entry = *(netif->addr_hint);
-      if (etharp_cached_entry < ARP_TABLE_SIZE) {
-#endif /* LWIP_NETIF_HWADDRHINT */
-        if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
-#if ETHARP_TABLE_MATCH_NETIF
-            (arp_table[etharp_cached_entry].netif == netif) &&
-#endif
-            (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
-          /* the per-pcb-cached entry is stable and the right one! */
-          ETHARP_STATS_INC(etharp.cachehit);
-          return etharp_output_to_arp_index(netif, q, etharp_cached_entry);
-        }
-#if LWIP_NETIF_HWADDRHINT
-      }
-    }
-#endif /* LWIP_NETIF_HWADDRHINT */
-
-    /* find stable entry: do this here since this is a critical path for
-       throughput and etharp_find_entry() is kind of slow */
-    for (i = 0; i < ARP_TABLE_SIZE; i++) {
-      if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
-#if ETHARP_TABLE_MATCH_NETIF
-          (arp_table[i].netif == netif) &&
-#endif
-          (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) {
-        /* found an existing, stable entry */
-        ETHARP_SET_HINT(netif, i);
-        return etharp_output_to_arp_index(netif, q, i);
-      }
-    }
-    /* no stable entry found, use the (slower) query function:
-       queue on destination Ethernet address belonging to ipaddr */
-    return etharp_query(netif, dst_addr, q);
-  }
-
-  /* continuation for multicast/broadcast destinations */
-  /* obtain source Ethernet address of the given interface */
-  /* send packet directly on the link */
-  return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP);
-}
-
-/**
- * Send an ARP request for the given IP address and/or queue a packet.
- *
- * If the IP address was not yet in the cache, a pending ARP cache entry
- * is added and an ARP request is sent for the given address. The packet
- * is queued on this entry.
- *
- * If the IP address was already pending in the cache, a new ARP request
- * is sent for the given address. The packet is queued on this entry.
- *
- * If the IP address was already stable in the cache, and a packet is
- * given, it is directly sent and no ARP request is sent out.
- *
- * If the IP address was already stable in the cache, and no packet is
- * given, an ARP request is sent out.
- *
- * @param netif The lwIP network interface on which ipaddr
- * must be queried for.
- * @param ipaddr The IP address to be resolved.
- * @param q If non-NULL, a pbuf that must be delivered to the IP address.
- * q is not freed by this function.
- *
- * @note q must only be ONE packet, not a packet queue!
- *
- * @return
- * - ERR_BUF Could not make room for Ethernet header.
- * - ERR_MEM Hardware address unknown, and no more ARP entries available
- *   to query for address or queue the packet.
- * - ERR_MEM Could not queue packet due to memory shortage.
- * - ERR_RTE No route to destination (no gateway to external networks).
- * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
- *
- */
-err_t
-etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
-{
-  struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
-  err_t result = ERR_MEM;
-  int is_new_entry = 0;
-  s8_t i; /* ARP entry index */
-
-  /* non-unicast address? */
-  if (ip4_addr_isbroadcast(ipaddr, netif) ||
-      ip4_addr_ismulticast(ipaddr) ||
-      ip4_addr_isany(ipaddr)) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
-    return ERR_ARG;
-  }
-
-  /* find entry in ARP cache, ask to create entry if queueing packet */
-  i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif);
-
-  /* could not find or create entry? */
-  if (i < 0) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
-    if (q) {
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
-      ETHARP_STATS_INC(etharp.memerr);
-    }
-    return (err_t)i;
-  }
-
-  /* mark a fresh entry as pending (we just sent a request) */
-  if (arp_table[i].state == ETHARP_STATE_EMPTY) {
-    is_new_entry = 1;
-    arp_table[i].state = ETHARP_STATE_PENDING;
-    /* record network interface for re-sending arp request in etharp_tmr */
-    arp_table[i].netif = netif;
-  }
-
-  /* { i is either a STABLE or (new or existing) PENDING entry } */
-  LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
-  ((arp_table[i].state == ETHARP_STATE_PENDING) ||
-   (arp_table[i].state >= ETHARP_STATE_STABLE)));
-
-  /* do we have a new entry? or an implicit query request? */
-  if (is_new_entry || (q == NULL)) {
-    /* try to resolve it; send out ARP request */
-    result = etharp_request(netif, ipaddr);
-    if (result != ERR_OK) {
-      /* ARP request couldn't be sent */
-      /* We don't re-send arp request in etharp_tmr, but we still queue packets,
-         since this failure could be temporary, and the next packet calling
-         etharp_query again could lead to sending the queued packets. */
-    }
-    if (q == NULL) {
-      return result;
-    }
-  }
-
-  /* packet given? */
-  LWIP_ASSERT("q != NULL", q != NULL);
-  /* stable entry? */
-  if (arp_table[i].state >= ETHARP_STATE_STABLE) {
-    /* we have a valid IP->Ethernet address mapping */
-    ETHARP_SET_HINT(netif, i);
-    /* send the packet */
-    result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP);
-  /* pending entry? (either just created or already pending */
-  } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
-    /* entry is still pending, queue the given packet 'q' */
-    struct pbuf *p;
-    int copy_needed = 0;
-    /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
-     * to copy the whole queue into a new PBUF_RAM (see bug #11400)
-     * PBUF_ROMs can be left as they are, since ROM must not get changed. */
-    p = q;
-    while (p) {
-      LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
-      if (p->type != PBUF_ROM) {
-        copy_needed = 1;
-        break;
-      }
-      p = p->next;
-    }
-    if (copy_needed) {
-      /* copy the whole packet into new pbufs */
-      p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
-      if (p != NULL) {
-        if (pbuf_copy(p, q) != ERR_OK) {
-          pbuf_free(p);
-          p = NULL;
-        }
-      }
-    } else {
-      /* referencing the old pbuf is enough */
-      p = q;
-      pbuf_ref(p);
-    }
-    /* packet could be taken over? */
-    if (p != NULL) {
-      /* queue packet ... */
-#if ARP_QUEUEING
-      struct etharp_q_entry *new_entry;
-      /* allocate a new arp queue entry */
-      new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
-      if (new_entry != NULL) {
-        unsigned int qlen = 0;
-        new_entry->next = 0;
-        new_entry->p = p;
-        if (arp_table[i].q != NULL) {
-          /* queue was already existent, append the new entry to the end */
-          struct etharp_q_entry *r;
-          r = arp_table[i].q;
-          qlen++;
-          while (r->next != NULL) {
-            r = r->next;
-            qlen++;
-          }
-          r->next = new_entry;
-        } else {
-          /* queue did not exist, first item in queue */
-          arp_table[i].q = new_entry;
-        }
-#if ARP_QUEUE_LEN
-        if (qlen >= ARP_QUEUE_LEN) {
-          struct etharp_q_entry *old;
-          old = arp_table[i].q;
-          arp_table[i].q = arp_table[i].q->next;
-          pbuf_free(old->p);
-          memp_free(MEMP_ARP_QUEUE, old);
-        }
-#endif
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
-        result = ERR_OK;
-      } else {
-        /* the pool MEMP_ARP_QUEUE is empty */
-        pbuf_free(p);
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
-        result = ERR_MEM;
-      }
-#else /* ARP_QUEUEING */
-      /* always queue one packet per ARP request only, freeing a previously queued packet */
-      if (arp_table[i].q != NULL) {
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
-        pbuf_free(arp_table[i].q);
-      }
-      arp_table[i].q = p;
-      result = ERR_OK;
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
-#endif /* ARP_QUEUEING */
-    } else {
-      ETHARP_STATS_INC(etharp.memerr);
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
-      result = ERR_MEM;
-    }
-  }
-  return result;
-}
-
-/**
- * Send a raw ARP packet (opcode and all addresses can be modified)
- *
- * @param netif the lwip network interface on which to send the ARP packet
- * @param ethsrc_addr the source MAC address for the ethernet header
- * @param ethdst_addr the destination MAC address for the ethernet header
- * @param hwsrc_addr the source MAC address for the ARP protocol header
- * @param ipsrc_addr the source IP address for the ARP protocol header
- * @param hwdst_addr the destination MAC address for the ARP protocol header
- * @param ipdst_addr the destination IP address for the ARP protocol header
- * @param opcode the type of the ARP packet
- * @return ERR_OK if the ARP packet has been sent
- *         ERR_MEM if the ARP packet couldn't be allocated
- *         any other err_t on failure
- */
-static err_t
-etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
-           const struct eth_addr *ethdst_addr,
-           const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
-           const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
-           const u16_t opcode)
-{
-  struct pbuf *p;
-  err_t result = ERR_OK;
-  struct etharp_hdr *hdr;
-
-  LWIP_ASSERT("netif != NULL", netif != NULL);
-
-  /* allocate a pbuf for the outgoing ARP request packet */
-  p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM);
-  /* could allocate a pbuf for an ARP request? */
-  if (p == NULL) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
-      ("etharp_raw: could not allocate pbuf for ARP request.\n"));
-    ETHARP_STATS_INC(etharp.memerr);
-    return ERR_MEM;
-  }
-  LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
-              (p->len >= SIZEOF_ETHARP_HDR));
-
-  hdr = (struct etharp_hdr *)p->payload;
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
-  hdr->opcode = lwip_htons(opcode);
-
-  LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
-              (netif->hwaddr_len == ETH_HWADDR_LEN));
-
-  /* Write the ARP MAC-Addresses */
-  ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
-  ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
-  /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
-   * structure packing. */
-  IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
-  IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
-
-  hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
-  hdr->proto = PP_HTONS(ETHTYPE_IP);
-  /* set hwlen and protolen */
-  hdr->hwlen = ETH_HWADDR_LEN;
-  hdr->protolen = sizeof(ip4_addr_t);
-
-  /* send ARP query */
-#if LWIP_AUTOIP
-  /* If we are using Link-Local, all ARP packets that contain a Link-Local
-   * 'sender IP address' MUST be sent using link-layer broadcast instead of
-   * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
-  if(ip4_addr_islinklocal(ipsrc_addr)) {
-    ethernet_output(netif, p, ethsrc_addr, &ethbroadcast, ETHTYPE_ARP);
-  } else
-#endif /* LWIP_AUTOIP */
-  {
-    ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP);
-  }
-
-  ETHARP_STATS_INC(etharp.xmit);
-  /* free ARP query packet */
-  pbuf_free(p);
-  p = NULL;
-  /* could not allocate pbuf for ARP request */
-
-  return result;
-}
-
-/**
- * Send an ARP request packet asking for ipaddr to a specific eth address.
- * Used to send unicast request to refresh the ARP table just before an entry
- * times out
- *
- * @param netif the lwip network interface on which to send the request
- * @param ipaddr the IP address for which to ask
- * @param hw_dst_addr the ethernet address to send this packet to
- * @return ERR_OK if the request has been sent
- *         ERR_MEM if the ARP packet couldn't be allocated
- *         any other err_t on failure
- */
-static err_t
-etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr)
-{
-  return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr,
-                    (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), &ethzero,
-                    ipaddr, ARP_REQUEST);
-}
-
-/**
- * Send an ARP request packet asking for ipaddr.
- *
- * @param netif the lwip network interface on which to send the request
- * @param ipaddr the IP address for which to ask
- * @return ERR_OK if the request has been sent
- *         ERR_MEM if the ARP packet couldn't be allocated
- *         any other err_t on failure
- */
-err_t
-etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
-{
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
-  return etharp_request_dst(netif, ipaddr, &ethbroadcast);
-}
-#endif /* LWIP_IPV4 && LWIP_ARP */
-
-#endif /* LWIP_ARP || LWIP_ETHERNET */

+ 0 - 393
components/net/lwip-2.0.0/src/core/ipv4/icmp.c

@@ -1,393 +0,0 @@
-/**
- * @file
- * ICMP - Internet Control Message Protocol
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-/* Some ICMP messages should be passed to the transport protocols. This
-   is not implemented. */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/icmp.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/ip.h"
-#include "lwip/def.h"
-#include "lwip/stats.h"
-
-#include <string.h>
-
-/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
- * used to modify and send a response packet (and to 1 if this is not the case,
- * e.g. when link header is stripped of when receiving) */
-#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
-#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
-
-/* The amount of data from the original packet to return in a dest-unreachable */
-#define ICMP_DEST_UNREACH_DATASIZE 8
-
-static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
-
-/**
- * Processes ICMP input packets, called from ip_input().
- *
- * Currently only processes icmp echo requests and sends
- * out the echo response.
- *
- * @param p the icmp echo request packet, p->payload pointing to the icmp header
- * @param inp the netif on which this packet was received
- */
-void
-icmp_input(struct pbuf *p, struct netif *inp)
-{
-  u8_t type;
-#ifdef LWIP_DEBUG
-  u8_t code;
-#endif /* LWIP_DEBUG */
-  struct icmp_echo_hdr *iecho;
-  const struct ip_hdr *iphdr_in;
-  s16_t hlen;
-  const ip4_addr_t* src;
-
-  ICMP_STATS_INC(icmp.recv);
-  MIB2_STATS_INC(mib2.icmpinmsgs);
-
-  iphdr_in = ip4_current_header();
-  hlen = IPH_HL(iphdr_in) * 4;
-  if (hlen < IP_HLEN) {
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen));
-    goto lenerr;
-  }
-  if (p->len < sizeof(u16_t)*2) {
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
-    goto lenerr;
-  }
-
-  type = *((u8_t *)p->payload);
-#ifdef LWIP_DEBUG
-  code = *(((u8_t *)p->payload)+1);
-#endif /* LWIP_DEBUG */
-  switch (type) {
-  case ICMP_ER:
-    /* This is OK, echo reply might have been parsed by a raw PCB
-       (as obviously, an echo request has been sent, too). */
-    MIB2_STATS_INC(mib2.icmpinechoreps);
-    break;
-  case ICMP_ECHO:
-    MIB2_STATS_INC(mib2.icmpinechos);
-    src = ip4_current_dest_addr();
-    /* multicast destination address? */
-    if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
-#if LWIP_MULTICAST_PING
-      /* For multicast, use address of receiving interface as source address */
-      src = netif_ip4_addr(inp);
-#else /* LWIP_MULTICAST_PING */
-      LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n"));
-      goto icmperr;
-#endif /* LWIP_MULTICAST_PING */
-    }
-    /* broadcast destination address? */
-    if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) {
-#if LWIP_BROADCAST_PING
-      /* For broadcast, use address of receiving interface as source address */
-      src = netif_ip4_addr(inp);
-#else /* LWIP_BROADCAST_PING */
-      LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n"));
-      goto icmperr;
-#endif /* LWIP_BROADCAST_PING */
-    }
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
-    if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
-      LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
-      goto lenerr;
-    }
-#if CHECKSUM_CHECK_ICMP
-    IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
-      if (inet_chksum_pbuf(p) != 0) {
-        LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
-        pbuf_free(p);
-        ICMP_STATS_INC(icmp.chkerr);
-        MIB2_STATS_INC(mib2.icmpinerrors);
-        return;
-      }
-    }
-#endif
-#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
-    if (pbuf_header(p, (hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
-      /* p is not big enough to contain link headers
-       * allocate a new one and copy p into it
-       */
-      struct pbuf *r;
-      /* allocate new packet buffer with space for link headers */
-      r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM);
-      if (r == NULL) {
-        LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
-        goto icmperr;
-      }
-      if (r->len < hlen + sizeof(struct icmp_echo_hdr)) {
-        LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header"));
-        pbuf_free(r);
-        goto icmperr;
-      }
-      /* copy the ip header */
-      MEMCPY(r->payload, iphdr_in, hlen);
-      /* switch r->payload back to icmp header (cannot fail) */
-      if (pbuf_header(r, -hlen)) {
-        LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
-        pbuf_free(r);
-        goto icmperr;
-      }
-      /* copy the rest of the packet without ip header */
-      if (pbuf_copy(r, p) != ERR_OK) {
-        LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed"));
-        pbuf_free(r);
-        goto icmperr;
-      }
-      /* free the original p */
-      pbuf_free(p);
-      /* we now have an identical copy of p that has room for link headers */
-      p = r;
-    } else {
-      /* restore p->payload to point to icmp header (cannot fail) */
-      if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
-        LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
-        goto icmperr;
-      }
-    }
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
-    /* At this point, all checks are OK. */
-    /* We generate an answer by switching the dest and src ip addresses,
-     * setting the icmp type to ECHO_RESPONSE and updating the checksum. */
-    iecho = (struct icmp_echo_hdr *)p->payload;
-    if (pbuf_header(p, hlen)) {
-      LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
-    } else {
-      err_t ret;
-      struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
-      ip4_addr_copy(iphdr->src, *src);
-      ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
-      ICMPH_TYPE_SET(iecho, ICMP_ER);
-#if CHECKSUM_GEN_ICMP
-      IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
-        /* adjust the checksum */
-        if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
-          iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
-        } else {
-          iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
-        }
-      }
-#if LWIP_CHECKSUM_CTRL_PER_NETIF
-      else {
-        iecho->chksum = 0;
-      }
-#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
-#else /* CHECKSUM_GEN_ICMP */
-      iecho->chksum = 0;
-#endif /* CHECKSUM_GEN_ICMP */
-
-      /* Set the correct TTL and recalculate the header checksum. */
-      IPH_TTL_SET(iphdr, ICMP_TTL);
-      IPH_CHKSUM_SET(iphdr, 0);
-#if CHECKSUM_GEN_IP
-      IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
-        IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen));
-      }
-#endif /* CHECKSUM_GEN_IP */
-
-      ICMP_STATS_INC(icmp.xmit);
-      /* increase number of messages attempted to send */
-      MIB2_STATS_INC(mib2.icmpoutmsgs);
-      /* increase number of echo replies attempted to send */
-      MIB2_STATS_INC(mib2.icmpoutechoreps);
-
-      /* send an ICMP packet */
-      ret = ip4_output_if(p, src, LWIP_IP_HDRINCL,
-                   ICMP_TTL, 0, IP_PROTO_ICMP, inp);
-      if (ret != ERR_OK) {
-        LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret)));
-      }
-    }
-    break;
-  default:
-    if (type == ICMP_DUR) {
-      MIB2_STATS_INC(mib2.icmpindestunreachs);
-    } else if (type == ICMP_TE) {
-      MIB2_STATS_INC(mib2.icmpindestunreachs);
-    } else if (type == ICMP_PP) {
-      MIB2_STATS_INC(mib2.icmpinparmprobs);
-    } else if (type == ICMP_SQ) {
-      MIB2_STATS_INC(mib2.icmpinsrcquenchs);
-    } else if (type == ICMP_RD) {
-      MIB2_STATS_INC(mib2.icmpinredirects);
-    } else if (type == ICMP_TS) {
-      MIB2_STATS_INC(mib2.icmpintimestamps);
-    } else if (type == ICMP_TSR) {
-      MIB2_STATS_INC(mib2.icmpintimestampreps);
-    } else if (type == ICMP_AM) {
-      MIB2_STATS_INC(mib2.icmpinaddrmasks);
-    } else if (type == ICMP_AMR) {
-      MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
-    }
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
-                (s16_t)type, (s16_t)code));
-    ICMP_STATS_INC(icmp.proterr);
-    ICMP_STATS_INC(icmp.drop);
-  }
-  pbuf_free(p);
-  return;
-lenerr:
-  pbuf_free(p);
-  ICMP_STATS_INC(icmp.lenerr);
-  MIB2_STATS_INC(mib2.icmpinerrors);
-  return;
-#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
-icmperr:
-  pbuf_free(p);
-  ICMP_STATS_INC(icmp.err);
-  MIB2_STATS_INC(mib2.icmpinerrors);
-  return;
-#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
-}
-
-/**
- * Send an icmp 'destination unreachable' packet, called from ip_input() if
- * the transport layer protocol is unknown and from udp_input() if the local
- * port is not bound.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- *          p->payload pointing to the IP header
- * @param t type of the 'unreachable' packet
- */
-void
-icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
-{
-  MIB2_STATS_INC(mib2.icmpoutdestunreachs);
-  icmp_send_response(p, ICMP_DUR, t);
-}
-
-#if IP_FORWARD || IP_REASSEMBLY
-/**
- * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
- *
- * @param p the input packet for which the 'time exceeded' should be sent,
- *          p->payload pointing to the IP header
- * @param t type of the 'time exceeded' packet
- */
-void
-icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
-{
-  MIB2_STATS_INC(mib2.icmpouttimeexcds);
-  icmp_send_response(p, ICMP_TE, t);
-}
-
-#endif /* IP_FORWARD || IP_REASSEMBLY */
-
-/**
- * Send an icmp packet in response to an incoming packet.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- *          p->payload pointing to the IP header
- * @param type Type of the ICMP header
- * @param code Code of the ICMP header
- */
-static void
-icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
-{
-  struct pbuf *q;
-  struct ip_hdr *iphdr;
-  /* we can use the echo header here */
-  struct icmp_echo_hdr *icmphdr;
-  ip4_addr_t iphdr_src;
-  struct netif *netif;
-
-  /* increase number of messages attempted to send */
-  MIB2_STATS_INC(mib2.icmpoutmsgs);
-
-  /* ICMP header + IP header + 8 bytes of data */
-  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
-                 PBUF_RAM);
-  if (q == NULL) {
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
-    MIB2_STATS_INC(mib2.icmpouterrors);
-    return;
-  }
-  LWIP_ASSERT("check that first pbuf can hold icmp message",
-             (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
-
-  iphdr = (struct ip_hdr *)p->payload;
-  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
-  ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
-  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
-  ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);
-  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
-
-  icmphdr = (struct icmp_echo_hdr *)q->payload;
-  icmphdr->type = type;
-  icmphdr->code = code;
-  icmphdr->id = 0;
-  icmphdr->seqno = 0;
-
-  /* copy fields from original packet */
-  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
-          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
-
-  ip4_addr_copy(iphdr_src, iphdr->src);
-#ifdef LWIP_HOOK_IP4_ROUTE_SRC
-  {
-    ip4_addr_t iphdr_dst;
-    ip4_addr_copy(iphdr_dst, iphdr->dest);
-    netif = ip4_route_src(&iphdr_src, &iphdr_dst);
-  }
-#else
-  netif = ip4_route(&iphdr_src);
-#endif
-  if (netif != NULL) {
-    /* calculate checksum */
-    icmphdr->chksum = 0;
-#if CHECKSUM_GEN_ICMP
-    IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
-      icmphdr->chksum = inet_chksum(icmphdr, q->len);
-    }
-#endif
-    ICMP_STATS_INC(icmp.xmit);
-    ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
-  }
-  pbuf_free(q);
-}
-
-#endif /* LWIP_IPV4 && LWIP_ICMP */

+ 0 - 792
components/net/lwip-2.0.0/src/core/ipv4/igmp.c

@@ -1,792 +0,0 @@
-/**
- * @file
- * IGMP - Internet Group Management Protocol
- *
- * @defgroup igmp IGMP
- * @ingroup ip4
- * To be called from TCPIP thread
- */
-
-/*
- * Copyright (c) 2002 CITEL Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file is a contribution to the lwIP TCP/IP stack.
- * The Swedish Institute of Computer Science and Adam Dunkels
- * are specifically granted permission to redistribute this
- * source code.
-*/
-
-/*-------------------------------------------------------------
-Note 1)
-Although the rfc requires V1 AND V2 capability
-we will only support v2 since now V1 is very old (August 1989)
-V1 can be added if required
-
-a debug print and statistic have been implemented to
-show this up.
--------------------------------------------------------------
--------------------------------------------------------------
-Note 2)
-A query for a specific group address (as opposed to ALLHOSTS)
-has now been implemented as I am unsure if it is required
-
-a debug print and statistic have been implemented to
-show this up.
--------------------------------------------------------------
--------------------------------------------------------------
-Note 3)
-The router alert rfc 2113 is implemented in outgoing packets
-but not checked rigorously incoming
--------------------------------------------------------------
-Steve Reynolds
-------------------------------------------------------------*/
-
-/*-----------------------------------------------------------------------------
- * RFC 988  - Host extensions for IP multicasting                         - V0
- * RFC 1054 - Host extensions for IP multicasting                         -
- * RFC 1112 - Host extensions for IP multicasting                         - V1
- * RFC 2236 - Internet Group Management Protocol, Version 2               - V2  <- this code is based on this RFC (it's the "de facto" standard)
- * RFC 3376 - Internet Group Management Protocol, Version 3               - V3
- * RFC 4604 - Using Internet Group Management Protocol Version 3...       - V3+
- * RFC 2113 - IP Router Alert Option                                      -
- *----------------------------------------------------------------------------*/
-
-/*-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/igmp.h"
-#include "lwip/debug.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/ip.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/stats.h"
-#include "lwip/prot/igmp.h"
-
-#include "string.h"
-
-static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr);
-static err_t  igmp_remove_group(struct netif* netif, struct igmp_group *group);
-static void   igmp_timeout(struct netif *netif, struct igmp_group *group);
-static void   igmp_start_timer(struct igmp_group *group, u8_t max_time);
-static void   igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
-static err_t  igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif);
-static void   igmp_send(struct netif *netif, struct igmp_group *group, u8_t type);
-
-static ip4_addr_t     allsystems;
-static ip4_addr_t     allrouters;
-
-/**
- * Initialize the IGMP module
- */
-void
-igmp_init(void)
-{
-  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n"));
-
-  IP4_ADDR(&allsystems, 224, 0, 0, 1);
-  IP4_ADDR(&allrouters, 224, 0, 0, 2);
-}
-
-/**
- * Start IGMP processing on interface
- *
- * @param netif network interface on which start IGMP processing
- */
-err_t
-igmp_start(struct netif *netif)
-{
-  struct igmp_group* group;
-
-  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif));
-
-  group = igmp_lookup_group(netif, &allsystems);
-
-  if (group != NULL) {
-    group->group_state = IGMP_GROUP_IDLE_MEMBER;
-    group->use++;
-
-    /* Allow the igmp messages at the MAC level */
-    if (netif->igmp_mac_filter != NULL) {
-      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
-      ip4_addr_debug_print_val(IGMP_DEBUG, allsystems);
-      LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
-      netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER);
-    }
-
-    return ERR_OK;
-  }
-
-  return ERR_MEM;
-}
-
-/**
- * Stop IGMP processing on interface
- *
- * @param netif network interface on which stop IGMP processing
- */
-err_t
-igmp_stop(struct netif *netif)
-{
-  struct igmp_group *group = netif_igmp_data(netif);
-
-  netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL);
-
-  while (group != NULL) {
-    struct igmp_group *next = group->next; /* avoid use-after-free below */
-
-    /* disable the group at the MAC level */
-    if (netif->igmp_mac_filter != NULL) {
-      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
-      ip4_addr_debug_print(IGMP_DEBUG, &group->group_address);
-      LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
-      netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
-    }
-
-    /* free group */
-    memp_free(MEMP_IGMP_GROUP, group);
-
-    /* move to "next" */
-    group = next;
-  }
-  return ERR_OK;
-}
-
-/**
- * Report IGMP memberships for this interface
- *
- * @param netif network interface on which report IGMP memberships
- */
-void
-igmp_report_groups(struct netif *netif)
-{
-  struct igmp_group *group = netif_igmp_data(netif);
-
-  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif));
-
-  /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
-  if(group != NULL) {
-    group = group->next;
-  }
-  
-  while (group != NULL) {
-    igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
-    group = group->next;
-  }
-}
-
-/**
- * Search for a group in the global igmp_group_list
- *
- * @param ifp the network interface for which to look
- * @param addr the group ip address to search for
- * @return a struct igmp_group* if the group has been found,
- *         NULL if the group wasn't found.
- */
-struct igmp_group *
-igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
-{
-  struct igmp_group *group = netif_igmp_data(ifp);
-
-  while (group != NULL) {
-    if (ip4_addr_cmp(&(group->group_address), addr)) {
-      return group;
-    }
-    group = group->next;
-  }
-
-  /* to be clearer, we return NULL here instead of
-   * 'group' (which is also NULL at this point).
-   */
-  return NULL;
-}
-
-/**
- * Search for a specific igmp group and create a new one if not found-
- *
- * @param ifp the network interface for which to look
- * @param addr the group ip address to search
- * @return a struct igmp_group*,
- *         NULL on memory error.
- */
-struct igmp_group *
-igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
-{
-  struct igmp_group *group;
-
-  /* Search if the group already exists */
-  group = igmp_lookfor_group(ifp, addr);
-  if (group != NULL) {
-    /* Group already exists. */
-    return group;
-  }
-
-  /* Group doesn't exist yet, create a new one */
-  group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
-  if (group != NULL) {
-    ip4_addr_set(&(group->group_address), addr);
-    group->timer              = 0; /* Not running */
-    group->group_state        = IGMP_GROUP_NON_MEMBER;
-    group->last_reporter_flag = 0;
-    group->use                = 0;
-    group->next               = netif_igmp_data(ifp);
-
-    netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
-  }
-
-  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
-  ip4_addr_debug_print(IGMP_DEBUG, addr);
-  LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp));
-
-  return group;
-}
-
-/**
- * Remove a group in the global igmp_group_list, but don't free it yet
- *
- * @param group the group to remove from the global igmp_group_list
- * @return ERR_OK if group was removed from the list, an err_t otherwise
- */
-static err_t
-igmp_remove_group(struct netif* netif, struct igmp_group *group)
-{
-  err_t err = ERR_OK;
-
-  /* Is it the first group? */
-  if (netif_igmp_data(netif) == group) {
-    netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next);
-  } else {
-    /* look for group further down the list */
-    struct igmp_group *tmpGroup;
-    for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
-      if (tmpGroup->next == group) {
-        tmpGroup->next = group->next;
-        break;
-      }
-    }
-    /* Group not found in the global igmp_group_list */
-    if (tmpGroup == NULL) {
-      err = ERR_ARG;
-    }
-  }
-
-  return err;
-}
-
-/**
- * Called from ip_input() if a new IGMP packet is received.
- *
- * @param p received igmp packet, p->payload pointing to the igmp header
- * @param inp network interface on which the packet was received
- * @param dest destination ip address of the igmp packet
- */
-void
-igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
-{
-  struct igmp_msg*   igmp;
-  struct igmp_group* group;
-  struct igmp_group* groupref;
-
-  IGMP_STATS_INC(igmp.recv);
-
-  /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
-  if (p->len < IGMP_MINLEN) {
-    pbuf_free(p);
-    IGMP_STATS_INC(igmp.lenerr);
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
-    return;
-  }
-
-  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
-  ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src));
-  LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
-  ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest));
-  LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp));
-
-  /* Now calculate and check the checksum */
-  igmp = (struct igmp_msg *)p->payload;
-  if (inet_chksum(igmp, p->len)) {
-    pbuf_free(p);
-    IGMP_STATS_INC(igmp.chkerr);
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n"));
-    return;
-  }
-
-  /* Packet is ok so find an existing group */
-  group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */
-
-  /* If group can be found or create... */
-  if (!group) {
-    pbuf_free(p);
-    IGMP_STATS_INC(igmp.drop);
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
-    return;
-  }
-
-  /* NOW ACT ON THE INCOMING MESSAGE TYPE... */
-  switch (igmp->igmp_msgtype) {
-  case IGMP_MEMB_QUERY:
-    /* IGMP_MEMB_QUERY to the "all systems" address ? */
-    if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) {
-      /* THIS IS THE GENERAL QUERY */
-      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
-
-      if (igmp->igmp_maxresp == 0) {
-        IGMP_STATS_INC(igmp.rx_v1);
-        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
-        igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
-      } else {
-        IGMP_STATS_INC(igmp.rx_general);
-      }
-
-      groupref = netif_igmp_data(inp);
-      
-      /* Do not send messages on the all systems group address! */
-      /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
-      if(groupref != NULL) {
-        groupref = groupref->next;
-      }
-
-      while (groupref) {
-        igmp_delaying_member(groupref, igmp->igmp_maxresp);
-        groupref = groupref->next;
-      }
-    } else {
-      /* IGMP_MEMB_QUERY to a specific group ? */
-      if (!ip4_addr_isany(&igmp->igmp_group_address)) {
-        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
-        ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
-        if (ip4_addr_cmp(dest, &allsystems)) {
-          ip4_addr_t groupaddr;
-          LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
-          /* we first need to re-look for the group since we used dest last time */
-          ip4_addr_copy(groupaddr, igmp->igmp_group_address);
-          group = igmp_lookfor_group(inp, &groupaddr);
-        } else {
-          LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
-        }
-
-        if (group != NULL) {
-          IGMP_STATS_INC(igmp.rx_group);
-          igmp_delaying_member(group, igmp->igmp_maxresp);
-        } else {
-          IGMP_STATS_INC(igmp.drop);
-        }
-      } else {
-        IGMP_STATS_INC(igmp.proterr);
-      }
-    }
-    break;
-  case IGMP_V2_MEMB_REPORT:
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
-    IGMP_STATS_INC(igmp.rx_report);
-    if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
-      /* This is on a specific group we have already looked up */
-      group->timer = 0; /* stopped */
-      group->group_state = IGMP_GROUP_IDLE_MEMBER;
-      group->last_reporter_flag = 0;
-    }
-    break;
-  default:
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
-      igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp));
-    IGMP_STATS_INC(igmp.proterr);
-    break;
-  }
-
-  pbuf_free(p);
-  return;
-}
-
-/**
- * @ingroup igmp
- * Join a group on one network interface.
- *
- * @param ifaddr ip address of the network interface which should join a new group
- * @param groupaddr the ip address of the group which to join
- * @return ERR_OK if group was joined on the netif(s), an err_t otherwise
- */
-err_t
-igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
-{
-  err_t err = ERR_VAL; /* no matching interface */
-  struct netif *netif;
-
-  /* make sure it is multicast address */
-  LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
-  LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
-  /* loop through netif's */
-  netif = netif_list;
-  while (netif != NULL) {
-    /* Should we join this interface ? */
-    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
-      err = igmp_joingroup_netif(netif, groupaddr);
-      if (err != ERR_OK) {
-        /* Return an error even if some network interfaces are joined */
-        /** @todo undo any other netif already joined */
-        return err;
-      }
-    }
-    /* proceed to next network interface */
-    netif = netif->next;
-  }
-
-  return err;
-}
-
-/**
- * @ingroup igmp
- * Join a group on one network interface.
- *
- * @param netif the network interface which should join a new group
- * @param groupaddr the ip address of the group which to join
- * @return ERR_OK if group was joined on the netif, an err_t otherwise
- */
-err_t
-igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
-{
-  struct igmp_group *group;
-
-  /* make sure it is multicast address */
-  LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
-  LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
-  /* make sure it is an igmp-enabled netif */
-  LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
-
-  /* find group or create a new one if not found */
-  group = igmp_lookup_group(netif, groupaddr);
-
-  if (group != NULL) {
-    /* This should create a new group, check the state to make sure */
-    if (group->group_state != IGMP_GROUP_NON_MEMBER) {
-      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
-    } else {
-      /* OK - it was new group */
-      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: "));
-      ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
-      LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-
-      /* If first use of the group, allow the group at the MAC level */
-      if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
-        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD "));
-        ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
-        LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
-        netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER);
-      }
-
-      IGMP_STATS_INC(igmp.tx_join);
-      igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
-
-      igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
-
-      /* Need to work out where this timer comes from */
-      group->group_state = IGMP_GROUP_DELAYING_MEMBER;
-    }
-    /* Increment group use */
-    group->use++;
-    /* Join on this interface */
-    return ERR_OK;
-  } else {
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n"));
-    return ERR_MEM;
-  }
-}
-
-/**
- * @ingroup igmp
- * Leave a group on one network interface.
- *
- * @param ifaddr ip address of the network interface which should leave a group
- * @param groupaddr the ip address of the group which to leave
- * @return ERR_OK if group was left on the netif(s), an err_t otherwise
- */
-err_t
-igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
-{
-  err_t err = ERR_VAL; /* no matching interface */
-  struct netif *netif;
-
-  /* make sure it is multicast address */
-  LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
-  LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
-  /* loop through netif's */
-  netif = netif_list;
-  while (netif != NULL) {
-    /* Should we leave this interface ? */
-    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
-      err_t res = igmp_leavegroup_netif(netif, groupaddr);
-      if (err != ERR_OK) {
-        /* Store this result if we have not yet gotten a success */
-        err = res;
-      }
-    }
-    /* proceed to next network interface */
-    netif = netif->next;
-  }
-
-  return err;
-}
-
-/**
- * @ingroup igmp
- * Leave a group on one network interface.
- *
- * @param netif the network interface which should leave a group
- * @param groupaddr the ip address of the group which to leave
- * @return ERR_OK if group was left on the netif, an err_t otherwise
- */
-err_t
-igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
-{
-  struct igmp_group *group;
-
-  /* make sure it is multicast address */
-  LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
-  LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
-
-  /* make sure it is an igmp-enabled netif */
-  LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
-
-  /* find group */
-  group = igmp_lookfor_group(netif, groupaddr);
-
-  if (group != NULL) {
-    /* Only send a leave if the flag is set according to the state diagram */
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: "));
-    ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
-    LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
-
-    /* If there is no other use of the group */
-    if (group->use <= 1) {
-      /* Remove the group from the list */
-      igmp_remove_group(netif, group);
-
-      /* If we are the last reporter for this group */
-      if (group->last_reporter_flag) {
-        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n"));
-        IGMP_STATS_INC(igmp.tx_leave);
-        igmp_send(netif, group, IGMP_LEAVE_GROUP);
-      }
-
-      /* Disable the group at the MAC level */
-      if (netif->igmp_mac_filter != NULL) {
-        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL "));
-        ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
-        LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
-        netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER);
-      }
-
-      /* Free group struct */
-      memp_free(MEMP_IGMP_GROUP, group);
-    } else {
-      /* Decrement group use */
-      group->use--;
-    }
-    return ERR_OK;
-  } else {
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n"));
-    return ERR_VAL;
-  }
-}
-
-/**
- * The igmp timer function (both for NO_SYS=1 and =0)
- * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default).
- */
-void
-igmp_tmr(void)
-{
-  struct netif *netif = netif_list;
-
-  while (netif != NULL) {
-    struct igmp_group *group = netif_igmp_data(netif);
-
-    while (group != NULL) {
-      if (group->timer > 0) {
-        group->timer--;
-        if (group->timer == 0) {
-          igmp_timeout(netif, group);
-        }
-      }
-      group = group->next;
-    }
-    netif = netif->next;
-  }
-}
-
-/**
- * Called if a timeout for one group is reached.
- * Sends a report for this group.
- *
- * @param group an igmp_group for which a timeout is reached
- */
-static void
-igmp_timeout(struct netif *netif, struct igmp_group *group)
-{
-  /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group
-     (unless it is the allsystems group) */
-  if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
-      (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
-    ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address));
-    LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif));
-
-    group->group_state = IGMP_GROUP_IDLE_MEMBER;
-    
-    IGMP_STATS_INC(igmp.tx_report);
-    igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
-  }
-}
-
-/**
- * Start a timer for an igmp group
- *
- * @param group the igmp_group for which to start a timer
- * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with
- *        every call to igmp_tmr())
- */
-static void
-igmp_start_timer(struct igmp_group *group, u8_t max_time)
-{
-#ifdef LWIP_RAND
-  group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1;
-#else /* LWIP_RAND */
-  /* ATTENTION: use this only if absolutely necessary! */
-  group->timer = max_time / 2;
-#endif /* LWIP_RAND */
-
-  if (group->timer == 0) {
-    group->timer = 1;
-  }
-}
-
-/**
- * Delaying membership report for a group if necessary
- *
- * @param group the igmp_group for which "delaying" membership report
- * @param maxresp query delay
- */
-static void
-igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
-{
-  if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
-     ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
-      ((group->timer == 0) || (maxresp < group->timer)))) {
-    igmp_start_timer(group, maxresp);
-    group->group_state = IGMP_GROUP_DELAYING_MEMBER;
-  }
-}
-
-
-/**
- * Sends an IP packet on a network interface. This function constructs the IP header
- * and calculates the IP header checksum. If the source IP address is NULL,
- * the IP address of the outgoing network interface is filled in as source address.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IP header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the
- *         IP  address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param netif the netif on which to send this packet
- * @return ERR_OK if the packet was sent OK
- *         ERR_BUF if p doesn't have enough space for IP/LINK headers
- *         returns errors returned by netif->output
- */
-static err_t
-igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif)
-{
-  /* This is the "router alert" option */
-  u16_t ra[2];
-  ra[0] = PP_HTONS(ROUTER_ALERT);
-  ra[1] = 0x0000; /* Router shall examine packet */
-  IGMP_STATS_INC(igmp.xmit);
-  return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
-}
-
-/**
- * Send an igmp packet to a specific group.
- *
- * @param group the group to which to send the packet
- * @param type the type of igmp packet to send
- */
-static void
-igmp_send(struct netif *netif, struct igmp_group *group, u8_t type)
-{
-  struct pbuf*     p    = NULL;
-  struct igmp_msg* igmp = NULL;
-  ip4_addr_t   src  = *IP4_ADDR_ANY4;
-  ip4_addr_t*  dest = NULL;
-
-  /* IP header + "router alert" option + IGMP header */
-  p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
-
-  if (p) {
-    igmp = (struct igmp_msg *)p->payload;
-    LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
-               (p->len >= sizeof(struct igmp_msg)));
-    ip4_addr_copy(src, *netif_ip4_addr(netif));
-
-    if (type == IGMP_V2_MEMB_REPORT) {
-      dest = &(group->group_address);
-      ip4_addr_copy(igmp->igmp_group_address, group->group_address);
-      group->last_reporter_flag = 1; /* Remember we were the last to report */
-    } else {
-      if (type == IGMP_LEAVE_GROUP) {
-        dest = &allrouters;
-        ip4_addr_copy(igmp->igmp_group_address, group->group_address);
-      }
-    }
-
-    if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {
-      igmp->igmp_msgtype  = type;
-      igmp->igmp_maxresp  = 0;
-      igmp->igmp_checksum = 0;
-      igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
-
-      igmp_ip_output_if(p, &src, dest, netif);
-    }
-
-    pbuf_free(p);
-  } else {
-    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
-    IGMP_STATS_INC(igmp.memerr);
-  }
-}
-
-#endif /* LWIP_IPV4 && LWIP_IGMP */

+ 0 - 1072
components/net/lwip-2.0.0/src/core/ipv4/ip4.c

@@ -1,1072 +0,0 @@
-/**
- * @file
- * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
- *
- * @see ip_frag.c
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4
-
-#include "lwip/ip.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/ip4_frag.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/icmp.h"
-#include "lwip/igmp.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/priv/tcp_priv.h"
-#include "lwip/autoip.h"
-#include "lwip/stats.h"
-#include "lwip/prot/dhcp.h"
-
-#include <string.h>
-
-/** Set this to 0 in the rare case of wanting to call an extra function to
- * generate the IP checksum (in contrast to calculating it on-the-fly). */
-#ifndef LWIP_INLINE_IP_CHKSUM
-#if LWIP_CHECKSUM_CTRL_PER_NETIF
-#define LWIP_INLINE_IP_CHKSUM   0
-#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
-#define LWIP_INLINE_IP_CHKSUM   1
-#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
-#endif
-
-#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
-#define CHECKSUM_GEN_IP_INLINE  1
-#else
-#define CHECKSUM_GEN_IP_INLINE  0
-#endif
-
-#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
-#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
-
-/** Some defines for DHCP to let link-layer-addressed packets through while the
- * netif is down.
- * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port)
- * to return 1 if the port is accepted and 0 if the port is not accepted.
- */
-#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
-/* accept DHCP client port and custom port */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
-         || (LWIP_IP_ACCEPT_UDP_PORT(port)))
-#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-/* accept custom port only */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port))
-#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-/* accept DHCP client port only */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
-#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
-
-#else /* LWIP_DHCP */
-#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
-#endif /* LWIP_DHCP */
-
-/** The IP header ID of the next outgoing IP packet */
-static u16_t ip_id;
-
-#if LWIP_MULTICAST_TX_OPTIONS
-/** The default netif used for multicast */
-static struct netif* ip4_default_multicast_netif;
-
-/**
- * @ingroup ip4
- * Set a default netif for IPv4 multicast. */
-void
-ip4_set_default_multicast_netif(struct netif* default_multicast_netif)
-{
-  ip4_default_multicast_netif = default_multicast_netif;
-}
-#endif /* LWIP_MULTICAST_TX_OPTIONS */
-
-#ifdef LWIP_HOOK_IP4_ROUTE_SRC
-/**
- * Source based IPv4 routing must be fully implemented in
- * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters.
- */
-struct netif *
-ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src)
-{
-  if (src != NULL) {
-    /* when src==NULL, the hook is called from ip4_route(dest) */
-    struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src);
-    if (netif != NULL) {
-      return netif;
-    }
-  }
-  return ip4_route(dest);
-}
-#endif /* LWIP_HOOK_IP4_ROUTE_SRC */
-
-/**
- * Finds the appropriate network interface for a given IP address. It
- * searches the list of network interfaces linearly. A match is found
- * if the masked IP address of the network interface equals the masked
- * IP address given to the function.
- *
- * @param dest the destination IP address for which to find the route
- * @return the netif on which to send to reach dest
- */
-struct netif *
-ip4_route(const ip4_addr_t *dest)
-{
-  struct netif *netif;
-
-#if LWIP_MULTICAST_TX_OPTIONS
-  /* Use administratively selected interface for multicast by default */
-  if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) {
-    return ip4_default_multicast_netif;
-  }
-#endif /* LWIP_MULTICAST_TX_OPTIONS */
-
-  /* iterate through netifs */
-  for (netif = netif_list; netif != NULL; netif = netif->next) {
-    /* is the netif up, does it have a link and a valid address? */
-    if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
-      /* network mask matches? */
-      if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {
-        /* return netif on which to forward IP packet */
-        return netif;
-      }
-      /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */
-      if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) {
-        /* return netif on which to forward IP packet */
-        return netif;
-      }
-    }
-  }
-
-#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
-  /* loopif is disabled, looopback traffic is passed through any netif */
-  if (ip4_addr_isloopback(dest)) {
-    /* don't check for link on loopback traffic */
-    if (netif_is_up(netif_default)) {
-      return netif_default;
-    }
-    /* default netif is not up, just use any netif for loopback traffic */
-    for (netif = netif_list; netif != NULL; netif = netif->next) {
-      if (netif_is_up(netif)) {
-        return netif;
-      }
-    }
-    return NULL;
-  }
-#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
-
-#ifdef LWIP_HOOK_IP4_ROUTE_SRC
-  netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL);
-  if (netif != NULL) {
-    return netif;
-  }
-#elif defined(LWIP_HOOK_IP4_ROUTE)
-  netif = LWIP_HOOK_IP4_ROUTE(dest);
-  if (netif != NULL) {
-    return netif;
-  }
-#endif
-
-  if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||
-      ip4_addr_isany_val(*netif_ip4_addr(netif_default))) {
-    /* No matching netif found and default netif is not usable.
-       If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */
-    LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
-    IP_STATS_INC(ip.rterr);
-    MIB2_STATS_INC(mib2.ipoutnoroutes);
-    return NULL;
-  }
-
-  return netif_default;
-}
-
-#if IP_FORWARD
-/**
- * Determine whether an IP address is in a reserved set of addresses
- * that may not be forwarded, or whether datagrams to that destination
- * may be forwarded.
- * @param p the packet to forward
- * @return 1: can forward 0: discard
- */
-static int
-ip4_canforward(struct pbuf *p)
-{
-  u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr()));
-
-  if (p->flags & PBUF_FLAG_LLBCAST) {
-    /* don't route link-layer broadcasts */
-    return 0;
-  }
-  if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) {
-    /* don't route link-layer multicasts unless the destination address is an IP
-       multicast address */
-    return 0;
-  }
-  if (IP_EXPERIMENTAL(addr)) {
-    return 0;
-  }
-  if (IP_CLASSA(addr)) {
-    u32_t net = addr & IP_CLASSA_NET;
-    if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) {
-      /* don't route loopback packets */
-      return 0;
-    }
-  }
-  return 1;
-}
-
-/**
- * Forwards an IP packet. It finds an appropriate route for the
- * packet, decrements the TTL value of the packet, adjusts the
- * checksum and outputs the packet on the appropriate interface.
- *
- * @param p the packet to forward (p->payload points to IP header)
- * @param iphdr the IP header of the input packet
- * @param inp the netif on which this packet was received
- */
-static void
-ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
-{
-  struct netif *netif;
-
-  PERF_START;
-  LWIP_UNUSED_ARG(inp);
-
-  if (!ip4_canforward(p)) {
-    goto return_noroute;
-  }
-
-  /* RFC3927 2.7: do not forward link-local addresses */
-  if (ip4_addr_islinklocal(ip4_current_dest_addr())) {
-    LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()),
-      ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr())));
-    goto return_noroute;
-  }
-
-  /* Find network interface where to forward this IP packet to. */
-  netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr());
-  if (netif == NULL) {
-    LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
-      ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()),
-      ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr())));
-    /* @todo: send ICMP_DUR_NET? */
-    goto return_noroute;
-  }
-#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
-  /* Do not forward packets onto the same network interface on which
-   * they arrived. */
-  if (netif == inp) {
-    LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n"));
-    goto return_noroute;
-  }
-#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
-
-  /* decrement TTL */
-  IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
-  /* send ICMP if TTL == 0 */
-  if (IPH_TTL(iphdr) == 0) {
-    MIB2_STATS_INC(mib2.ipinhdrerrors);
-#if LWIP_ICMP
-    /* Don't send ICMP messages in response to ICMP messages */
-    if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
-      icmp_time_exceeded(p, ICMP_TE_TTL);
-    }
-#endif /* LWIP_ICMP */
-    return;
-  }
-
-  /* Incrementally update the IP checksum. */
-  if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
-    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
-  } else {
-    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
-  }
-
-  LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-    ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()),
-    ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr())));
-
-  IP_STATS_INC(ip.fw);
-  MIB2_STATS_INC(mib2.ipforwdatagrams);
-  IP_STATS_INC(ip.xmit);
-
-  PERF_STOP("ip4_forward");
-  /* don't fragment if interface has mtu set to 0 [loopif] */
-  if (netif->mtu && (p->tot_len > netif->mtu)) {
-    if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) {
-#if IP_FRAG
-      ip4_frag(p, netif, ip4_current_dest_addr());
-#else /* IP_FRAG */
-      /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */
-#endif /* IP_FRAG */
-    } else {
-#if LWIP_ICMP
-      /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */
-      icmp_dest_unreach(p, ICMP_DUR_FRAG);
-#endif /* LWIP_ICMP */
-    }
-    return;
-  }
-  /* transmit pbuf on chosen interface */
-  netif->output(netif, p, ip4_current_dest_addr());
-  return;
-return_noroute:
-  MIB2_STATS_INC(mib2.ipoutnoroutes);
-}
-#endif /* IP_FORWARD */
-
-/**
- * This function is called by the network interface device driver when
- * an IP packet is received. The function does the basic checks of the
- * IP header such as packet size being at least larger than the header
- * size etc. If the packet was not destined for us, the packet is
- * forwarded (using ip_forward). The IP checksum is always checked.
- *
- * Finally, the packet is sent to the upper layer protocol input function.
- *
- * @param p the received IP packet (p->payload points to IP header)
- * @param inp the netif on which this packet was received
- * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
- *         processed, but currently always returns ERR_OK)
- */
-err_t
-ip4_input(struct pbuf *p, struct netif *inp)
-{
-  struct ip_hdr *iphdr;
-  struct netif *netif;
-  u16_t iphdr_hlen;
-  u16_t iphdr_len;
-#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP
-  int check_ip_src = 1;
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */
-
-  IP_STATS_INC(ip.recv);
-  MIB2_STATS_INC(mib2.ipinreceives);
-
-  /* identify the IP header */
-  iphdr = (struct ip_hdr *)p->payload;
-  if (IPH_V(iphdr) != 4) {
-    LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", (u16_t)IPH_V(iphdr)));
-    ip4_debug_print(p);
-    pbuf_free(p);
-    IP_STATS_INC(ip.err);
-    IP_STATS_INC(ip.drop);
-    MIB2_STATS_INC(mib2.ipinhdrerrors);
-    return ERR_OK;
-  }
-
-#ifdef LWIP_HOOK_IP4_INPUT
-  if (LWIP_HOOK_IP4_INPUT(p, inp)) {
-    /* the packet has been eaten */
-    return ERR_OK;
-  }
-#endif
-
-  /* obtain IP header length in number of 32-bit words */
-  iphdr_hlen = IPH_HL(iphdr);
-  /* calculate IP header length in bytes */
-  iphdr_hlen *= 4;
-  /* obtain ip length in bytes */
-  iphdr_len = lwip_ntohs(IPH_LEN(iphdr));
-
-  /* Trim pbuf. This is especially required for packets < 60 bytes. */
-  if (iphdr_len < p->tot_len) {
-    pbuf_realloc(p, iphdr_len);
-  }
-
-  /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
-  if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len) || (iphdr_hlen < IP_HLEN)) {
-    if (iphdr_hlen < IP_HLEN) {
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("ip4_input: short IP header (%"U16_F" bytes) received, IP packet dropped\n", iphdr_hlen));
-    }
-    if (iphdr_hlen > p->len) {
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
-        iphdr_hlen, p->len));
-    }
-    if (iphdr_len > p->tot_len) {
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
-        iphdr_len, p->tot_len));
-    }
-    /* free (drop) packet pbufs */
-    pbuf_free(p);
-    IP_STATS_INC(ip.lenerr);
-    IP_STATS_INC(ip.drop);
-    MIB2_STATS_INC(mib2.ipindiscards);
-    return ERR_OK;
-  }
-
-  /* verify checksum */
-#if CHECKSUM_CHECK_IP
-  IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) {
-    if (inet_chksum(iphdr, iphdr_hlen) != 0) {
-
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
-      ip4_debug_print(p);
-      pbuf_free(p);
-      IP_STATS_INC(ip.chkerr);
-      IP_STATS_INC(ip.drop);
-      MIB2_STATS_INC(mib2.ipinhdrerrors);
-      return ERR_OK;
-    }
-  }
-#endif
-
-  /* copy IP addresses to aligned ip_addr_t */
-  ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest);
-  ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src);
-
-  /* match packet against an interface, i.e. is this packet for us? */
-  if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
-#if LWIP_IGMP
-    if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) {
-      /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */
-      ip4_addr_t allsystems;
-      IP4_ADDR(&allsystems, 224, 0, 0, 1);
-      if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) &&
-          ip4_addr_isany(ip4_current_src_addr())) {
-        check_ip_src = 0;
-      }
-      netif = inp;
-    } else {
-      netif = NULL;
-    }
-#else /* LWIP_IGMP */
-    if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) {
-      netif = inp;
-    } else {
-      netif = NULL;
-    }
-#endif /* LWIP_IGMP */
-  } else {
-    /* start trying with inp. if that's not acceptable, start walking the
-       list of configured netifs.
-       'first' is used as a boolean to mark whether we started walking the list */
-    int first = 1;
-    netif = inp;
-    do {
-      LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
-          ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)),
-          ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)),
-          ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)),
-          ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif))));
-
-      /* interface is up and configured? */
-      if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) {
-        /* unicast to this interface address? */
-        if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) ||
-            /* or broadcast on this interface network address? */
-            ip4_addr_isbroadcast(ip4_current_dest_addr(), netif)
-#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
-            || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK))
-#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
-            ) {
-          LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n",
-              netif->name[0], netif->name[1]));
-          /* break out of for loop */
-          break;
-        }
-#if LWIP_AUTOIP
-        /* connections to link-local addresses must persist after changing
-           the netif's address (RFC3927 ch. 1.9) */
-        if (autoip_accept_packet(netif, ip4_current_dest_addr())) {
-          LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n",
-              netif->name[0], netif->name[1]));
-          /* break out of for loop */
-          break;
-        }
-#endif /* LWIP_AUTOIP */
-      }
-      if (first) {
-        first = 0;
-        netif = netif_list;
-      } else {
-        netif = netif->next;
-      }
-      if (netif == inp) {
-        netif = netif->next;
-      }
-    } while (netif != NULL);
-  }
-
-#if IP_ACCEPT_LINK_LAYER_ADDRESSING
-  /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
-   * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
-   * According to RFC 1542 section 3.1.1, referred by RFC 2131).
-   *
-   * If you want to accept private broadcast communication while a netif is down,
-   * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
-   *
-   * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
-   */
-  if (netif == NULL) {
-    /* remote port is DHCP server? */
-    if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
-      struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n",
-        lwip_ntohs(udphdr->dest)));
-      if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
-        LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n"));
-        netif = inp;
-        check_ip_src = 0;
-      }
-    }
-  }
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
-
-  /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
-#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING
-  if (check_ip_src
-#if IP_ACCEPT_LINK_LAYER_ADDRESSING
-  /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
-      && !ip4_addr_isany_val(*ip4_current_src_addr())
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
-     )
-#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */
-  {
-    if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) ||
-        (ip4_addr_ismulticast(ip4_current_src_addr()))) {
-      /* packet source is not valid */
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n"));
-      /* free (drop) packet pbufs */
-      pbuf_free(p);
-      IP_STATS_INC(ip.drop);
-      MIB2_STATS_INC(mib2.ipinaddrerrors);
-      MIB2_STATS_INC(mib2.ipindiscards);
-      return ERR_OK;
-    }
-  }
-
-  /* packet not for us? */
-  if (netif == NULL) {
-    /* packet not for us, route or discard */
-    LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n"));
-#if IP_FORWARD
-    /* non-broadcast packet? */
-    if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) {
-      /* try to forward IP packet on (other) interfaces */
-      ip4_forward(p, iphdr, inp);
-    } else
-#endif /* IP_FORWARD */
-    {
-      MIB2_STATS_INC(mib2.ipinaddrerrors);
-      MIB2_STATS_INC(mib2.ipindiscards);
-    }
-    pbuf_free(p);
-    return ERR_OK;
-  }
-  /* packet consists of multiple fragments? */
-  if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
-#if IP_REASSEMBLY /* packet fragment reassembly code present? */
-    LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n",
-      lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)));
-    /* reassemble the packet*/
-    p = ip4_reass(p);
-    /* packet not fully reassembled yet? */
-    if (p == NULL) {
-      return ERR_OK;
-    }
-    iphdr = (struct ip_hdr *)p->payload;
-#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
-    pbuf_free(p);
-    LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
-      lwip_ntohs(IPH_OFFSET(iphdr))));
-    IP_STATS_INC(ip.opterr);
-    IP_STATS_INC(ip.drop);
-    /* unsupported protocol feature */
-    MIB2_STATS_INC(mib2.ipinunknownprotos);
-    return ERR_OK;
-#endif /* IP_REASSEMBLY */
-  }
-
-#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
-
-#if LWIP_IGMP
-  /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
-  if ((iphdr_hlen > IP_HLEN) &&  (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
-#else
-  if (iphdr_hlen > IP_HLEN) {
-#endif /* LWIP_IGMP */
-    LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
-    pbuf_free(p);
-    IP_STATS_INC(ip.opterr);
-    IP_STATS_INC(ip.drop);
-    /* unsupported protocol feature */
-    MIB2_STATS_INC(mib2.ipinunknownprotos);
-    return ERR_OK;
-  }
-#endif /* IP_OPTIONS_ALLOWED == 0 */
-
-  /* send to upper layers */
-  LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n"));
-  ip4_debug_print(p);
-  LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
-
-  ip_data.current_netif = netif;
-  ip_data.current_input_netif = inp;
-  ip_data.current_ip4_header = iphdr;
-  ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4;
-
-#if LWIP_RAW
-  /* raw input did not eat the packet? */
-  if (raw_input(p, inp) == 0)
-#endif /* LWIP_RAW */
-  {
-    pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */
-
-    switch (IPH_PROTO(iphdr)) {
-#if LWIP_UDP
-    case IP_PROTO_UDP:
-#if LWIP_UDPLITE
-    case IP_PROTO_UDPLITE:
-#endif /* LWIP_UDPLITE */
-      MIB2_STATS_INC(mib2.ipindelivers);
-      udp_input(p, inp);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-    case IP_PROTO_TCP:
-      MIB2_STATS_INC(mib2.ipindelivers);
-      tcp_input(p, inp);
-      break;
-#endif /* LWIP_TCP */
-#if LWIP_ICMP
-    case IP_PROTO_ICMP:
-      MIB2_STATS_INC(mib2.ipindelivers);
-      icmp_input(p, inp);
-      break;
-#endif /* LWIP_ICMP */
-#if LWIP_IGMP
-    case IP_PROTO_IGMP:
-      igmp_input(p, inp, ip4_current_dest_addr());
-      break;
-#endif /* LWIP_IGMP */
-    default:
-#if LWIP_ICMP
-      /* send ICMP destination protocol unreachable unless is was a broadcast */
-      if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) &&
-          !ip4_addr_ismulticast(ip4_current_dest_addr())) {
-        pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */
-        p->payload = iphdr;
-        icmp_dest_unreach(p, ICMP_DUR_PROTO);
-      }
-#endif /* LWIP_ICMP */
-      pbuf_free(p);
-
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr)));
-
-      IP_STATS_INC(ip.proterr);
-      IP_STATS_INC(ip.drop);
-      MIB2_STATS_INC(mib2.ipinunknownprotos);
-    }
-  }
-
-  /* @todo: this is not really necessary... */
-  ip_data.current_netif = NULL;
-  ip_data.current_input_netif = NULL;
-  ip_data.current_ip4_header = NULL;
-  ip_data.current_ip_header_tot_len = 0;
-  ip4_addr_set_any(ip4_current_src_addr());
-  ip4_addr_set_any(ip4_current_dest_addr());
-
-  return ERR_OK;
-}
-
-/**
- * Sends an IP packet on a network interface. This function constructs
- * the IP header and calculates the IP header checksum. If the source
- * IP address is NULL, the IP address of the outgoing network
- * interface is filled in as source address.
- * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already
- * include an IP header and p->payload points to it instead of the data.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IP header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the
- *         IP  address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- * @param netif the netif on which to send this packet
- * @return ERR_OK if the packet was sent OK
- *         ERR_BUF if p doesn't have enough space for IP/LINK headers
- *         returns errors returned by netif->output
- *
- * @note ip_id: RFC791 "some host may be able to simply use
- *  unique identifiers independent of destination"
- */
-err_t
-ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-             u8_t ttl, u8_t tos,
-             u8_t proto, struct netif *netif)
-{
-#if IP_OPTIONS_SEND
-  return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
-}
-
-/**
- * Same as ip_output_if() but with the possibility to include IP options:
- *
- * @ param ip_options pointer to the IP options, copied into the IP header
- * @ param optlen length of ip_options
- */
-err_t
-ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-       u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
-       u16_t optlen)
-{
-#endif /* IP_OPTIONS_SEND */
-  const ip4_addr_t *src_used = src;
-  if (dest != LWIP_IP_HDRINCL) {
-    if (ip4_addr_isany(src)) {
-      src_used = netif_ip4_addr(netif);
-    }
-  }
-
-#if IP_OPTIONS_SEND
-  return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif,
-    ip_options, optlen);
-#else /* IP_OPTIONS_SEND */
-  return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif);
-#endif /* IP_OPTIONS_SEND */
-}
-
-/**
- * Same as ip_output_if() but 'src' address is not replaced by netif address
- * when it is 'any'.
- */
-err_t
-ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-             u8_t ttl, u8_t tos,
-             u8_t proto, struct netif *netif)
-{
-#if IP_OPTIONS_SEND
-  return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0);
-}
-
-/**
- * Same as ip_output_if_opt() but 'src' address is not replaced by netif address
- * when it is 'any'.
- */
-err_t
-ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-       u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
-       u16_t optlen)
-{
-#endif /* IP_OPTIONS_SEND */
-  struct ip_hdr *iphdr;
-  ip4_addr_t dest_addr;
-#if CHECKSUM_GEN_IP_INLINE
-  u32_t chk_sum = 0;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  MIB2_STATS_INC(mib2.ipoutrequests);
-
-  /* Should the IP header be generated or is it already included in p? */
-  if (dest != LWIP_IP_HDRINCL) {
-    u16_t ip_hlen = IP_HLEN;
-#if IP_OPTIONS_SEND
-    u16_t optlen_aligned = 0;
-    if (optlen != 0) {
-#if CHECKSUM_GEN_IP_INLINE
-      int i;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-      /* round up to a multiple of 4 */
-      optlen_aligned = ((optlen + 3) & ~3);
-      ip_hlen += optlen_aligned;
-      /* First write in the IP options */
-      if (pbuf_header(p, optlen_aligned)) {
-        LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n"));
-        IP_STATS_INC(ip.err);
-        MIB2_STATS_INC(mib2.ipoutdiscards);
-        return ERR_BUF;
-      }
-      MEMCPY(p->payload, ip_options, optlen);
-      if (optlen < optlen_aligned) {
-        /* zero the remaining bytes */
-        memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
-      }
-#if CHECKSUM_GEN_IP_INLINE
-      for (i = 0; i < optlen_aligned/2; i++) {
-        chk_sum += ((u16_t*)p->payload)[i];
-      }
-#endif /* CHECKSUM_GEN_IP_INLINE */
-    }
-#endif /* IP_OPTIONS_SEND */
-    /* generate IP header */
-    if (pbuf_header(p, IP_HLEN)) {
-      LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n"));
-
-      IP_STATS_INC(ip.err);
-      MIB2_STATS_INC(mib2.ipoutdiscards);
-      return ERR_BUF;
-    }
-
-    iphdr = (struct ip_hdr *)p->payload;
-    LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
-               (p->len >= sizeof(struct ip_hdr)));
-
-    IPH_TTL_SET(iphdr, ttl);
-    IPH_PROTO_SET(iphdr, proto);
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += LWIP_MAKE_U16(proto, ttl);
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
-    /* dest cannot be NULL here */
-    ip4_addr_copy(iphdr->dest, *dest);
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
-    chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-
-    IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
-    IPH_TOS_SET(iphdr, tos);
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
-#endif /* CHECKSUM_GEN_IP_INLINE */
-    IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += iphdr->_len;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-    IPH_OFFSET_SET(iphdr, 0);
-    IPH_ID_SET(iphdr, lwip_htons(ip_id));
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += iphdr->_id;
-#endif /* CHECKSUM_GEN_IP_INLINE */
-    ++ip_id;
-
-    if (src == NULL) {
-      ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4);
-    } else {
-      /* src cannot be NULL here */
-      ip4_addr_copy(iphdr->src, *src);
-    }
-
-#if CHECKSUM_GEN_IP_INLINE
-    chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
-    chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
-    chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
-    chk_sum = (chk_sum >> 16) + chk_sum;
-    chk_sum = ~chk_sum;
-    IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
-      iphdr->_chksum = (u16_t)chk_sum; /* network order */
-    }
-#if LWIP_CHECKSUM_CTRL_PER_NETIF
-    else {
-      IPH_CHKSUM_SET(iphdr, 0);
-    }
-#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
-#else /* CHECKSUM_GEN_IP_INLINE */
-    IPH_CHKSUM_SET(iphdr, 0);
-#if CHECKSUM_GEN_IP
-    IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
-      IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
-    }
-#endif /* CHECKSUM_GEN_IP */
-#endif /* CHECKSUM_GEN_IP_INLINE */
-  } else {
-    /* IP header already included in p */
-    iphdr = (struct ip_hdr *)p->payload;
-    ip4_addr_copy(dest_addr, iphdr->dest);
-    dest = &dest_addr;
-  }
-
-  IP_STATS_INC(ip.xmit);
-
-  LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
-  ip4_debug_print(p);
-
-#if ENABLE_LOOPBACK
-  if (ip4_addr_cmp(dest, netif_ip4_addr(netif))
-#if !LWIP_HAVE_LOOPIF
-      || ip4_addr_isloopback(dest)
-#endif /* !LWIP_HAVE_LOOPIF */
-      ) {
-    /* Packet to self, enqueue it for loopback */
-    LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
-    return netif_loop_output(netif, p);
-  }
-#if LWIP_MULTICAST_TX_OPTIONS
-  if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
-    netif_loop_output(netif, p);
-  }
-#endif /* LWIP_MULTICAST_TX_OPTIONS */
-#endif /* ENABLE_LOOPBACK */
-#if IP_FRAG
-  /* don't fragment if interface has mtu set to 0 [loopif] */
-  if (netif->mtu && (p->tot_len > netif->mtu)) {
-    return ip4_frag(p, netif, dest);
-  }
-#endif /* IP_FRAG */
-
-  LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n"));
-  return netif->output(netif, p, dest);
-}
-
-/**
- * Simple interface to ip_output_if. It finds the outgoing network
- * interface and calls upon ip_output_if to do the actual work.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IP header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the
- *         IP  address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- *
- * @return ERR_RTE if no route is found
- *         see ip_output_if() for more return values
- */
-err_t
-ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-          u8_t ttl, u8_t tos, u8_t proto)
-{
-  struct netif *netif;
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  if ((netif = ip4_route_src(dest, src)) == NULL) {
-    LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
-    IP_STATS_INC(ip.rterr);
-    return ERR_RTE;
-  }
-
-  return ip4_output_if(p, src, dest, ttl, tos, proto, netif);
-}
-
-#if LWIP_NETIF_HWADDRHINT
-/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
- *  before calling ip_output_if.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IP header and p->payload points to that IP header)
- * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the
- *         IP  address of the netif used to send is used as source address)
- * @param dest the destination IP address to send the packet to
- * @param ttl the TTL value to be set in the IP header
- * @param tos the TOS value to be set in the IP header
- * @param proto the PROTOCOL to be set in the IP header
- * @param addr_hint address hint pointer set to netif->addr_hint before
- *        calling ip_output_if()
- *
- * @return ERR_RTE if no route is found
- *         see ip_output_if() for more return values
- */
-err_t
-ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
-          u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
-{
-  struct netif *netif;
-  err_t err;
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  if ((netif = ip4_route_src(dest, src)) == NULL) {
-    LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
-    IP_STATS_INC(ip.rterr);
-    return ERR_RTE;
-  }
-
-  NETIF_SET_HWADDRHINT(netif, addr_hint);
-  err = ip4_output_if(p, src, dest, ttl, tos, proto, netif);
-  NETIF_SET_HWADDRHINT(netif, NULL);
-
-  return err;
-}
-#endif /* LWIP_NETIF_HWADDRHINT*/
-
-#if IP_DEBUG
-/* Print an IP header by using LWIP_DEBUGF
- * @param p an IP packet, p->payload pointing to the IP header
- */
-void
-ip4_debug_print(struct pbuf *p)
-{
-  struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
-
-  LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" |  0x%02"X16_F" |     %5"U16_F"     | (v, hl, tos, len)\n",
-                    (u16_t)IPH_V(iphdr),
-                    (u16_t)IPH_HL(iphdr),
-                    (u16_t)IPH_TOS(iphdr),
-                    lwip_ntohs(IPH_LEN(iphdr))));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      |%"U16_F"%"U16_F"%"U16_F"|    %4"U16_F"   | (id, flags, offset)\n",
-                    lwip_ntohs(IPH_ID(iphdr)),
-                    (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1),
-                    (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1),
-                    (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1),
-                    (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |    0x%04"X16_F"     | (ttl, proto, chksum)\n",
-                    (u16_t)IPH_TTL(iphdr),
-                    (u16_t)IPH_PROTO(iphdr),
-                    lwip_ntohs(IPH_CHKSUM(iphdr))));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (src)\n",
-                    ip4_addr1_16(&iphdr->src),
-                    ip4_addr2_16(&iphdr->src),
-                    ip4_addr3_16(&iphdr->src),
-                    ip4_addr4_16(&iphdr->src)));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (dest)\n",
-                    ip4_addr1_16(&iphdr->dest),
-                    ip4_addr2_16(&iphdr->dest),
-                    ip4_addr3_16(&iphdr->dest),
-                    ip4_addr4_16(&iphdr->dest)));
-  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
-}
-#endif /* IP_DEBUG */
-
-#endif /* LWIP_IPV4 */

+ 0 - 331
components/net/lwip-2.0.0/src/core/ipv4/ip4_addr.c

@@ -1,331 +0,0 @@
-/**
- * @file
- * This is the IPv4 address tools implementation.
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4
-
-#include "lwip/ip_addr.h"
-#include "lwip/netif.h"
-
-/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
-const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
-const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
-
-/**
- * Determine if an address is a broadcast address on a network interface
- *
- * @param addr address to be checked
- * @param netif the network interface against which the address is checked
- * @return returns non-zero if the address is a broadcast address
- */
-u8_t
-ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif)
-{
-  ip4_addr_t ipaddr;
-  ip4_addr_set_u32(&ipaddr, addr);
-
-  /* all ones (broadcast) or all zeroes (old skool broadcast) */
-  if ((~addr == IPADDR_ANY) ||
-      (addr == IPADDR_ANY)) {
-    return 1;
-  /* no broadcast support on this network interface? */
-  } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
-    /* the given address cannot be a broadcast address
-     * nor can we check against any broadcast addresses */
-    return 0;
-  /* address matches network interface address exactly? => no broadcast */
-  } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) {
-    return 0;
-  /*  on the same (sub) network... */
-  } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif))
-         /* ...and host identifier bits are all ones? =>... */
-          && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) ==
-           (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) {
-    /* => network broadcast address */
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-/** Checks if a netmask is valid (starting with ones, then only zeros)
- *
- * @param netmask the IPv4 netmask to check (in network byte order!)
- * @return 1 if the netmask is valid, 0 if it is not
- */
-u8_t
-ip4_addr_netmask_valid(u32_t netmask)
-{
-  u32_t mask;
-  u32_t nm_hostorder = lwip_htonl(netmask);
-
-  /* first, check for the first zero */
-  for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
-    if ((nm_hostorder & mask) == 0) {
-      break;
-    }
-  }
-  /* then check that there is no one */
-  for (; mask != 0; mask >>= 1) {
-    if ((nm_hostorder & mask) != 0) {
-      /* there is a one after the first zero -> invalid */
-      return 0;
-    }
-  }
-  /* no one after the first zero -> valid */
-  return 1;
-}
-
-/* Here for now until needed in other places in lwIP */
-#ifndef isprint
-#define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
-#define isprint(c)           in_range(c, 0x20, 0x7f)
-#define isdigit(c)           in_range(c, '0', '9')
-#define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
-#define islower(c)           in_range(c, 'a', 'z')
-#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#endif
-
-/**
- * Ascii internet address interpretation routine.
- * The value returned is in network order.
- *
- * @param cp IP address in ascii representation (e.g. "127.0.0.1")
- * @return ip address in network order
- */
-u32_t
-ipaddr_addr(const char *cp)
-{
-  ip4_addr_t val;
-
-  if (ip4addr_aton(cp, &val)) {
-    return ip4_addr_get_u32(&val);
-  }
-  return (IPADDR_NONE);
-}
-
-/**
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- *
- * @param cp IP address in ascii representation (e.g. "127.0.0.1")
- * @param addr pointer to which to save the ip address in network order
- * @return 1 if cp could be converted to addr, 0 on failure
- */
-int
-ip4addr_aton(const char *cp, ip4_addr_t *addr)
-{
-  u32_t val;
-  u8_t base;
-  char c;
-  u32_t parts[4];
-  u32_t *pp = parts;
-
-  c = *cp;
-  for (;;) {
-    /*
-     * Collect number up to ``.''.
-     * Values are specified as for C:
-     * 0x=hex, 0=octal, 1-9=decimal.
-     */
-    if (!isdigit(c)) {
-      return 0;
-    }
-    val = 0;
-    base = 10;
-    if (c == '0') {
-      c = *++cp;
-      if (c == 'x' || c == 'X') {
-        base = 16;
-        c = *++cp;
-      } else {
-        base = 8;
-      }
-    }
-    for (;;) {
-      if (isdigit(c)) {
-        val = (val * base) + (int)(c - '0');
-        c = *++cp;
-      } else if (base == 16 && isxdigit(c)) {
-        val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
-        c = *++cp;
-      } else {
-        break;
-      }
-    }
-    if (c == '.') {
-      /*
-       * Internet format:
-       *  a.b.c.d
-       *  a.b.c   (with c treated as 16 bits)
-       *  a.b (with b treated as 24 bits)
-       */
-      if (pp >= parts + 3) {
-        return 0;
-      }
-      *pp++ = val;
-      c = *++cp;
-    } else {
-      break;
-    }
-  }
-  /*
-   * Check for trailing characters.
-   */
-  if (c != '\0' && !isspace(c)) {
-    return 0;
-  }
-  /*
-   * Concoct the address according to
-   * the number of parts specified.
-   */
-  switch (pp - parts + 1) {
-
-  case 0:
-    return 0;       /* initial nondigit */
-
-  case 1:             /* a -- 32 bits */
-    break;
-
-  case 2:             /* a.b -- 8.24 bits */
-    if (val > 0xffffffUL) {
-      return 0;
-    }
-    if (parts[0] > 0xff) {
-      return 0;
-    }
-    val |= parts[0] << 24;
-    break;
-
-  case 3:             /* a.b.c -- 8.8.16 bits */
-    if (val > 0xffff) {
-      return 0;
-    }
-    if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
-      return 0;
-    }
-    val |= (parts[0] << 24) | (parts[1] << 16);
-    break;
-
-  case 4:             /* a.b.c.d -- 8.8.8.8 bits */
-    if (val > 0xff) {
-      return 0;
-    }
-    if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) {
-      return 0;
-    }
-    val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-    break;
-  default:
-    LWIP_ASSERT("unhandled", 0);
-    break;
-  }
-  if (addr) {
-    ip4_addr_set_u32(addr, lwip_htonl(val));
-  }
-  return 1;
-}
-
-/**
- * Convert numeric IP address into decimal dotted ASCII representation.
- * returns ptr to static buffer; not reentrant!
- *
- * @param addr ip address in network order to convert
- * @return pointer to a global static (!) buffer that holds the ASCII
- *         representation of addr
- */
-char*
-ip4addr_ntoa(const ip4_addr_t *addr)
-{
-  static char str[IP4ADDR_STRLEN_MAX];
-  return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
-}
-
-/**
- * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
- *
- * @param addr ip address in network order to convert
- * @param buf target buffer where the string is stored
- * @param buflen length of buf
- * @return either pointer to buf which now holds the ASCII
- *         representation of addr or NULL if buf was too small
- */
-char*
-ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
-{
-  u32_t s_addr;
-  char inv[3];
-  char *rp;
-  u8_t *ap;
-  u8_t rem;
-  u8_t n;
-  u8_t i;
-  int len = 0;
-
-  s_addr = ip4_addr_get_u32(addr);
-
-  rp = buf;
-  ap = (u8_t *)&s_addr;
-  for (n = 0; n < 4; n++) {
-    i = 0;
-    do {
-      rem = *ap % (u8_t)10;
-      *ap /= (u8_t)10;
-      inv[i++] = '0' + rem;
-    } while (*ap);
-    while (i--) {
-      if (len++ >= buflen) {
-        return NULL;
-      }
-      *rp++ = inv[i];
-    }
-    if (len++ >= buflen) {
-      return NULL;
-    }
-    *rp++ = '.';
-    ap++;
-  }
-  *--rp = 0;
-  return buf;
-}
-
-#endif /* LWIP_IPV4 */

+ 0 - 833
components/net/lwip-2.0.0/src/core/ipv4/ip4_frag.c

@@ -1,833 +0,0 @@
-/**
- * @file
- * This is the IPv4 packet segmentation and reassembly implementation.
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Jani Monoses <jani@iv.ro>
- *         Simon Goldschmidt
- * original reassembly code by Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV4
-
-#include "lwip/ip4_frag.h"
-#include "lwip/def.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/stats.h"
-#include "lwip/icmp.h"
-
-#include <string.h>
-
-#if IP_REASSEMBLY
-/**
- * The IP reassembly code currently has the following limitations:
- * - IP header options are not supported
- * - fragments must not overlap (e.g. due to different routes),
- *   currently, overlapping or duplicate fragments are thrown away
- *   if IP_REASS_CHECK_OVERLAP=1 (the default)!
- *
- * @todo: work with IP header options
- */
-
-/** Setting this to 0, you can turn off checking the fragments for overlapping
- * regions. The code gets a little smaller. Only use this if you know that
- * overlapping won't occur on your network! */
-#ifndef IP_REASS_CHECK_OVERLAP
-#define IP_REASS_CHECK_OVERLAP 1
-#endif /* IP_REASS_CHECK_OVERLAP */
-
-/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
- * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
- * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
- * is set to 1, so one datagram can be reassembled at a time, only. */
-#ifndef IP_REASS_FREE_OLDEST
-#define IP_REASS_FREE_OLDEST 1
-#endif /* IP_REASS_FREE_OLDEST */
-
-#define IP_REASS_FLAG_LASTFRAG 0x01
-
-/** This is a helper struct which holds the starting
- * offset and the ending offset of this fragment to
- * easily chain the fragments.
- * It has the same packing requirements as the IP header, since it replaces
- * the IP header in memory in incoming fragments (after copying it) to keep
- * track of the various fragments. (-> If the IP header doesn't need packing,
- * this struct doesn't need packing, too.)
- */
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct ip_reass_helper {
-  PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
-  PACK_STRUCT_FIELD(u16_t start);
-  PACK_STRUCT_FIELD(u16_t end);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
-
-#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB)  \
-  (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \
-   ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \
-   IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0
-
-/* global variables */
-static struct ip_reassdata *reassdatagrams;
-static u16_t ip_reass_pbufcount;
-
-/* function prototypes */
-static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
-static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
-
-/**
- * Reassembly timer base function
- * for both NO_SYS == 0 and 1 (!).
- *
- * Should be called every 1000 msec (defined by IP_TMR_INTERVAL).
- */
-void
-ip_reass_tmr(void)
-{
-  struct ip_reassdata *r, *prev = NULL;
-
-  r = reassdatagrams;
-  while (r != NULL) {
-    /* Decrement the timer. Once it reaches 0,
-     * clean up the incomplete fragment assembly */
-    if (r->timer > 0) {
-      r->timer--;
-      LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer));
-      prev = r;
-      r = r->next;
-    } else {
-      /* reassembly timed out */
-      struct ip_reassdata *tmp;
-      LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n"));
-      tmp = r;
-      /* get the next pointer before freeing */
-      r = r->next;
-      /* free the helper struct and all enqueued pbufs */
-      ip_reass_free_complete_datagram(tmp, prev);
-     }
-   }
-}
-
-/**
- * Free a datagram (struct ip_reassdata) and all its pbufs.
- * Updates the total count of enqueued pbufs (ip_reass_pbufcount),
- * SNMP counters and sends an ICMP time exceeded packet.
- *
- * @param ipr datagram to free
- * @param prev the previous datagram in the linked list
- * @return the number of pbufs freed
- */
-static int
-ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
-{
-  u16_t pbufs_freed = 0;
-  u16_t clen;
-  struct pbuf *p;
-  struct ip_reass_helper *iprh;
-
-  LWIP_ASSERT("prev != ipr", prev != ipr);
-  if (prev != NULL) {
-    LWIP_ASSERT("prev->next == ipr", prev->next == ipr);
-  }
-
-  MIB2_STATS_INC(mib2.ipreasmfails);
-#if LWIP_ICMP
-  iprh = (struct ip_reass_helper *)ipr->p->payload;
-  if (iprh->start == 0) {
-    /* The first fragment was received, send ICMP time exceeded. */
-    /* First, de-queue the first pbuf from r->p. */
-    p = ipr->p;
-    ipr->p = iprh->next_pbuf;
-    /* Then, copy the original header into it. */
-    SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
-    icmp_time_exceeded(p, ICMP_TE_FRAG);
-    clen = pbuf_clen(p);
-    LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
-    pbufs_freed += clen;
-    pbuf_free(p);
-  }
-#endif /* LWIP_ICMP */
-
-  /* First, free all received pbufs.  The individual pbufs need to be released
-     separately as they have not yet been chained */
-  p = ipr->p;
-  while (p != NULL) {
-    struct pbuf *pcur;
-    iprh = (struct ip_reass_helper *)p->payload;
-    pcur = p;
-    /* get the next pointer before freeing */
-    p = iprh->next_pbuf;
-    clen = pbuf_clen(pcur);
-    LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
-    pbufs_freed += clen;
-    pbuf_free(pcur);
-  }
-  /* Then, unchain the struct ip_reassdata from the list and free it. */
-  ip_reass_dequeue_datagram(ipr, prev);
-  LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed);
-  ip_reass_pbufcount -= pbufs_freed;
-
-  return pbufs_freed;
-}
-
-#if IP_REASS_FREE_OLDEST
-/**
- * Free the oldest datagram to make room for enqueueing new fragments.
- * The datagram 'fraghdr' belongs to is not freed!
- *
- * @param fraghdr IP header of the current fragment
- * @param pbufs_needed number of pbufs needed to enqueue
- *        (used for freeing other datagrams if not enough space)
- * @return the number of pbufs freed
- */
-static int
-ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
-{
-  /* @todo Can't we simply remove the last datagram in the
-   *       linked list behind reassdatagrams?
-   */
-  struct ip_reassdata *r, *oldest, *prev, *oldest_prev;
-  int pbufs_freed = 0, pbufs_freed_current;
-  int other_datagrams;
-
-  /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
-   * but don't free the datagram that 'fraghdr' belongs to! */
-  do {
-    oldest = NULL;
-    prev = NULL;
-    oldest_prev = NULL;
-    other_datagrams = 0;
-    r = reassdatagrams;
-    while (r != NULL) {
-      if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) {
-        /* Not the same datagram as fraghdr */
-        other_datagrams++;
-        if (oldest == NULL) {
-          oldest = r;
-          oldest_prev = prev;
-        } else if (r->timer <= oldest->timer) {
-          /* older than the previous oldest */
-          oldest = r;
-          oldest_prev = prev;
-        }
-      }
-      if (r->next != NULL) {
-        prev = r;
-      }
-      r = r->next;
-    }
-    if (oldest != NULL) {
-      pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
-      pbufs_freed += pbufs_freed_current;
-    }
-  } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
-  return pbufs_freed;
-}
-#endif /* IP_REASS_FREE_OLDEST */
-
-/**
- * Enqueues a new fragment into the fragment queue
- * @param fraghdr points to the new fragments IP hdr
- * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space)
- * @return A pointer to the queue location into which the fragment was enqueued
- */
-static struct ip_reassdata*
-ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
-{
-  struct ip_reassdata* ipr;
-#if ! IP_REASS_FREE_OLDEST
-  LWIP_UNUSED_ARG(clen);
-#endif
-
-  /* No matching previous fragment found, allocate a new reassdata struct */
-  ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
-  if (ipr == NULL) {
-#if IP_REASS_FREE_OLDEST
-    if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
-      ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
-    }
-    if (ipr == NULL)
-#endif /* IP_REASS_FREE_OLDEST */
-    {
-      IPFRAG_STATS_INC(ip_frag.memerr);
-      LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n"));
-      return NULL;
-    }
-  }
-  memset(ipr, 0, sizeof(struct ip_reassdata));
-  ipr->timer = IP_REASS_MAXAGE;
-
-  /* enqueue the new structure to the front of the list */
-  ipr->next = reassdatagrams;
-  reassdatagrams = ipr;
-  /* copy the ip header for later tests and input */
-  /* @todo: no ip options supported? */
-  SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN);
-  return ipr;
-}
-
-/**
- * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs.
- * @param ipr points to the queue entry to dequeue
- */
-static void
-ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
-{
-  /* dequeue the reass struct  */
-  if (reassdatagrams == ipr) {
-    /* it was the first in the list */
-    reassdatagrams = ipr->next;
-  } else {
-    /* it wasn't the first, so it must have a valid 'prev' */
-    LWIP_ASSERT("sanity check linked list", prev != NULL);
-    prev->next = ipr->next;
-  }
-
-  /* now we can free the ip_reassdata struct */
-  memp_free(MEMP_REASSDATA, ipr);
-}
-
-/**
- * Chain a new pbuf into the pbuf list that composes the datagram.  The pbuf list
- * will grow over time as  new pbufs are rx.
- * Also checks that the datagram passes basic continuity checks (if the last
- * fragment was received at least once).
- * @param ipr points to the reassembly state
- * @param new_p points to the pbuf for the current fragment
- * @return 0 if invalid, >0 otherwise
- */
-static int
-ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
-{
-  struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
-  struct pbuf *q;
-  u16_t offset, len;
-  struct ip_hdr *fraghdr;
-  int valid = 1;
-
-  /* Extract length and fragment offset from current fragment */
-  fraghdr = (struct ip_hdr*)new_p->payload;
-  len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
-  offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
-
-  /* overwrite the fragment's ip header from the pbuf with our helper struct,
-   * and setup the embedded helper structure. */
-  /* make sure the struct ip_reass_helper fits into the IP header */
-  LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN",
-              sizeof(struct ip_reass_helper) <= IP_HLEN);
-  iprh = (struct ip_reass_helper*)new_p->payload;
-  iprh->next_pbuf = NULL;
-  iprh->start = offset;
-  iprh->end = offset + len;
-
-  /* Iterate through until we either get to the end of the list (append),
-   * or we find one with a larger offset (insert). */
-  for (q = ipr->p; q != NULL;) {
-    iprh_tmp = (struct ip_reass_helper*)q->payload;
-    if (iprh->start < iprh_tmp->start) {
-      /* the new pbuf should be inserted before this */
-      iprh->next_pbuf = q;
-      if (iprh_prev != NULL) {
-        /* not the fragment with the lowest offset */
-#if IP_REASS_CHECK_OVERLAP
-        if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
-          /* fragment overlaps with previous or following, throw away */
-          goto freepbuf;
-        }
-#endif /* IP_REASS_CHECK_OVERLAP */
-        iprh_prev->next_pbuf = new_p;
-      } else {
-        /* fragment with the lowest offset */
-        ipr->p = new_p;
-      }
-      break;
-    } else if (iprh->start == iprh_tmp->start) {
-      /* received the same datagram twice: no need to keep the datagram */
-      goto freepbuf;
-#if IP_REASS_CHECK_OVERLAP
-    } else if (iprh->start < iprh_tmp->end) {
-      /* overlap: no need to keep the new datagram */
-      goto freepbuf;
-#endif /* IP_REASS_CHECK_OVERLAP */
-    } else {
-      /* Check if the fragments received so far have no holes. */
-      if (iprh_prev != NULL) {
-        if (iprh_prev->end != iprh_tmp->start) {
-          /* There is a fragment missing between the current
-           * and the previous fragment */
-          valid = 0;
-        }
-      }
-    }
-    q = iprh_tmp->next_pbuf;
-    iprh_prev = iprh_tmp;
-  }
-
-  /* If q is NULL, then we made it to the end of the list. Determine what to do now */
-  if (q == NULL) {
-    if (iprh_prev != NULL) {
-      /* this is (for now), the fragment with the highest offset:
-       * chain it to the last fragment */
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      iprh_prev->next_pbuf = new_p;
-      if (iprh_prev->end != iprh->start) {
-        valid = 0;
-      }
-    } else {
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("no previous fragment, this must be the first fragment!",
-        ipr->p == NULL);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      /* this is the first fragment we ever received for this ip datagram */
-      ipr->p = new_p;
-    }
-  }
-
-  /* At this point, the validation part begins: */
-  /* If we already received the last fragment */
-  if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) {
-    /* and had no holes so far */
-    if (valid) {
-      /* then check if the rest of the fragments is here */
-      /* Check if the queue starts with the first datagram */
-      if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) {
-        valid = 0;
-      } else {
-        /* and check that there are no holes after this datagram */
-        iprh_prev = iprh;
-        q = iprh->next_pbuf;
-        while (q != NULL) {
-          iprh = (struct ip_reass_helper*)q->payload;
-          if (iprh_prev->end != iprh->start) {
-            valid = 0;
-            break;
-          }
-          iprh_prev = iprh;
-          q = iprh->next_pbuf;
-        }
-        /* if still valid, all fragments are received
-         * (because to the MF==0 already arrived */
-        if (valid) {
-          LWIP_ASSERT("sanity check", ipr->p != NULL);
-          LWIP_ASSERT("sanity check",
-            ((struct ip_reass_helper*)ipr->p->payload) != iprh);
-          LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
-            iprh->next_pbuf == NULL);
-          LWIP_ASSERT("validate_datagram:datagram end!=datagram len",
-            iprh->end == ipr->datagram_len);
-        }
-      }
-    }
-    /* If valid is 0 here, there are some fragments missing in the middle
-     * (since MF == 0 has already arrived). Such datagrams simply time out if
-     * no more fragments are received... */
-    return valid;
-  }
-  /* If we come here, not all fragments were received, yet! */
-  return 0; /* not yet valid! */
-#if IP_REASS_CHECK_OVERLAP
-freepbuf:
-  ip_reass_pbufcount -= pbuf_clen(new_p);
-  pbuf_free(new_p);
-  return 0;
-#endif /* IP_REASS_CHECK_OVERLAP */
-}
-
-/**
- * Reassembles incoming IP fragments into an IP datagram.
- *
- * @param p points to a pbuf chain of the fragment
- * @return NULL if reassembly is incomplete, ? otherwise
- */
-struct pbuf *
-ip4_reass(struct pbuf *p)
-{
-  struct pbuf *r;
-  struct ip_hdr *fraghdr;
-  struct ip_reassdata *ipr;
-  struct ip_reass_helper *iprh;
-  u16_t offset, len, clen;
-
-  IPFRAG_STATS_INC(ip_frag.recv);
-  MIB2_STATS_INC(mib2.ipreasmreqds);
-
-  fraghdr = (struct ip_hdr*)p->payload;
-
-  if ((IPH_HL(fraghdr) * 4) != IP_HLEN) {
-    LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n"));
-    IPFRAG_STATS_INC(ip_frag.err);
-    goto nullreturn;
-  }
-
-  offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
-  len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
-
-  /* Check if we are allowed to enqueue more datagrams. */
-  clen = pbuf_clen(p);
-  if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
-#if IP_REASS_FREE_OLDEST
-    if (!ip_reass_remove_oldest_datagram(fraghdr, clen) ||
-        ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS))
-#endif /* IP_REASS_FREE_OLDEST */
-    {
-      /* No datagram could be freed and still too many pbufs enqueued */
-      LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n",
-        ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS));
-      IPFRAG_STATS_INC(ip_frag.memerr);
-      /* @todo: send ICMP time exceeded here? */
-      /* drop this pbuf */
-      goto nullreturn;
-    }
-  }
-
-  /* Look for the datagram the fragment belongs to in the current datagram queue,
-   * remembering the previous in the queue for later dequeueing. */
-  for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) {
-    /* Check if the incoming fragment matches the one currently present
-       in the reassembly buffer. If so, we proceed with copying the
-       fragment into the buffer. */
-    if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
-      LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n",
-        lwip_ntohs(IPH_ID(fraghdr))));
-      IPFRAG_STATS_INC(ip_frag.cachehit);
-      break;
-    }
-  }
-
-  if (ipr == NULL) {
-  /* Enqueue a new datagram into the datagram queue */
-    ipr = ip_reass_enqueue_new_datagram(fraghdr, clen);
-    /* Bail if unable to enqueue */
-    if (ipr == NULL) {
-      goto nullreturn;
-    }
-  } else {
-    if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
-      ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) {
-      /* ipr->iphdr is not the header from the first fragment, but fraghdr is
-       * -> copy fraghdr into ipr->iphdr since we want to have the header
-       * of the first fragment (for ICMP time exceeded and later, for copying
-       * all options, if supported)*/
-      SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
-    }
-  }
-  /* Track the current number of pbufs current 'in-flight', in order to limit
-  the number of fragments that may be enqueued at any one time */
-  ip_reass_pbufcount += clen;
-
-  /* At this point, we have either created a new entry or pointing
-   * to an existing one */
-
-  /* check for 'no more fragments', and update queue entry*/
-  if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
-    ipr->flags |= IP_REASS_FLAG_LASTFRAG;
-    ipr->datagram_len = offset + len;
-    LWIP_DEBUGF(IP_REASS_DEBUG,
-     ("ip4_reass: last fragment seen, total len %"S16_F"\n",
-      ipr->datagram_len));
-  }
-  /* find the right place to insert this pbuf */
-  /* @todo: trim pbufs if fragments are overlapping */
-  if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
-    struct ip_reassdata *ipr_prev;
-    /* the totally last fragment (flag more fragments = 0) was received at least
-     * once AND all fragments are received */
-    ipr->datagram_len += IP_HLEN;
-
-    /* save the second pbuf before copying the header over the pointer */
-    r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf;
-
-    /* copy the original ip header back to the first pbuf */
-    fraghdr = (struct ip_hdr*)(ipr->p->payload);
-    SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN);
-    IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len));
-    IPH_OFFSET_SET(fraghdr, 0);
-    IPH_CHKSUM_SET(fraghdr, 0);
-    /* @todo: do we need to set/calculate the correct checksum? */
-#if CHECKSUM_GEN_IP
-    IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) {
-      IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
-    }
-#endif /* CHECKSUM_GEN_IP */
-
-    p = ipr->p;
-
-    /* chain together the pbufs contained within the reass_data list. */
-    while (r != NULL) {
-      iprh = (struct ip_reass_helper*)r->payload;
-
-      /* hide the ip header for every succeeding fragment */
-      pbuf_header(r, -IP_HLEN);
-      pbuf_cat(p, r);
-      r = iprh->next_pbuf;
-    }
-
-    /* find the previous entry in the linked list */
-    if (ipr == reassdatagrams) {
-      ipr_prev = NULL;
-    } else {
-      for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
-        if (ipr_prev->next == ipr) {
-          break;
-        }
-      }
-    }
-
-    /* release the sources allocate for the fragment queue entry */
-    ip_reass_dequeue_datagram(ipr, ipr_prev);
-
-    /* and adjust the number of pbufs currently queued for reassembly. */
-    ip_reass_pbufcount -= pbuf_clen(p);
-
-    MIB2_STATS_INC(mib2.ipreasmoks);
-
-    /* Return the pbuf chain */
-    return p;
-  }
-  /* the datagram is not (yet?) reassembled completely */
-  LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount));
-  return NULL;
-
-nullreturn:
-  LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n"));
-  IPFRAG_STATS_INC(ip_frag.drop);
-  pbuf_free(p);
-  return NULL;
-}
-#endif /* IP_REASSEMBLY */
-
-#if IP_FRAG
-#if !LWIP_NETIF_TX_SINGLE_PBUF
-/** Allocate a new struct pbuf_custom_ref */
-static struct pbuf_custom_ref*
-ip_frag_alloc_pbuf_custom_ref(void)
-{
-  return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
-}
-
-/** Free a struct pbuf_custom_ref */
-static void
-ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
-{
-  LWIP_ASSERT("p != NULL", p != NULL);
-  memp_free(MEMP_FRAG_PBUF, p);
-}
-
-/** Free-callback function to free a 'struct pbuf_custom_ref', called by
- * pbuf_free. */
-static void
-ipfrag_free_pbuf_custom(struct pbuf *p)
-{
-  struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
-  LWIP_ASSERT("pcr != NULL", pcr != NULL);
-  LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
-  if (pcr->original != NULL) {
-    pbuf_free(pcr->original);
-  }
-  ip_frag_free_pbuf_custom_ref(pcr);
-}
-#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
-
-/**
- * Fragment an IP datagram if too large for the netif.
- *
- * Chop the datagram in MTU sized chunks and send them in order
- * by pointing PBUF_REFs into p.
- *
- * @param p ip packet to send
- * @param netif the netif on which to send
- * @param dest destination ip address to which to send
- *
- * @return ERR_OK if sent successfully, err_t otherwise
- */
-err_t
-ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
-{
-  struct pbuf *rambuf;
-#if !LWIP_NETIF_TX_SINGLE_PBUF
-  struct pbuf *newpbuf;
-#endif
-  struct ip_hdr *original_iphdr;
-  struct ip_hdr *iphdr;
-  const u16_t nfb = (netif->mtu - IP_HLEN) / 8;
-  u16_t left, fragsize;
-  u16_t ofo;
-  int last;
-  u16_t poff = IP_HLEN;
-  u16_t tmp;
-#if !LWIP_NETIF_TX_SINGLE_PBUF
-  u16_t newpbuflen = 0;
-  u16_t left_to_copy;
-#endif
-
-  original_iphdr = (struct ip_hdr *)p->payload;
-  iphdr = original_iphdr;
-  LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL);
-
-  /* Save original offset */
-  tmp = lwip_ntohs(IPH_OFFSET(iphdr));
-  ofo = tmp & IP_OFFMASK;
-  LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL);
-
-  left = p->tot_len - IP_HLEN;
-
-  while (left) {
-    /* Fill this fragment */
-    fragsize = LWIP_MIN(left, nfb * 8);
-
-#if LWIP_NETIF_TX_SINGLE_PBUF
-    rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM);
-    if (rambuf == NULL) {
-      goto memerr;
-    }
-    LWIP_ASSERT("this needs a pbuf in one piece!",
-      (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
-    poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff);
-    /* make room for the IP header */
-    if (pbuf_header(rambuf, IP_HLEN)) {
-      pbuf_free(rambuf);
-      goto memerr;
-    }
-    /* fill in the IP header */
-    SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
-    iphdr = (struct ip_hdr*)rambuf->payload;
-#else /* LWIP_NETIF_TX_SINGLE_PBUF */
-    /* When not using a static buffer, create a chain of pbufs.
-     * The first will be a PBUF_RAM holding the link and IP header.
-     * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
-     * but limited to the size of an mtu.
-     */
-    rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM);
-    if (rambuf == NULL) {
-      goto memerr;
-    }
-    LWIP_ASSERT("this needs a pbuf in one piece!",
-                (p->len >= (IP_HLEN)));
-    SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
-    iphdr = (struct ip_hdr *)rambuf->payload;
-
-    left_to_copy = fragsize;
-    while (left_to_copy) {
-      struct pbuf_custom_ref *pcr;
-      u16_t plen = p->len - poff;
-      newpbuflen = LWIP_MIN(left_to_copy, plen);
-      /* Is this pbuf already empty? */
-      if (!newpbuflen) {
-        poff = 0;
-        p = p->next;
-        continue;
-      }
-      pcr = ip_frag_alloc_pbuf_custom_ref();
-      if (pcr == NULL) {
-        pbuf_free(rambuf);
-        goto memerr;
-      }
-      /* Mirror this pbuf, although we might not need all of it. */
-      newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc,
-        (u8_t*)p->payload + poff, newpbuflen);
-      if (newpbuf == NULL) {
-        ip_frag_free_pbuf_custom_ref(pcr);
-        pbuf_free(rambuf);
-        goto memerr;
-      }
-      pbuf_ref(p);
-      pcr->original = p;
-      pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
-
-      /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
-       * so that it is removed when pbuf_dechain is later called on rambuf.
-       */
-      pbuf_cat(rambuf, newpbuf);
-      left_to_copy -= newpbuflen;
-      if (left_to_copy) {
-        poff = 0;
-        p = p->next;
-      }
-    }
-    poff += newpbuflen;
-#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
-
-    /* Correct header */
-    last = (left <= netif->mtu - IP_HLEN);
-
-    /* Set new offset and MF flag */
-    tmp = (IP_OFFMASK & (ofo));
-    if (!last) {
-      tmp = tmp | IP_MF;
-    }
-    IPH_OFFSET_SET(iphdr, lwip_htons(tmp));
-    IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN));
-    IPH_CHKSUM_SET(iphdr, 0);
-#if CHECKSUM_GEN_IP
-    IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
-      IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
-    }
-#endif /* CHECKSUM_GEN_IP */
-
-    /* No need for separate header pbuf - we allowed room for it in rambuf
-     * when allocated.
-     */
-    netif->output(netif, rambuf, dest);
-    IPFRAG_STATS_INC(ip_frag.xmit);
-
-    /* Unfortunately we can't reuse rambuf - the hardware may still be
-     * using the buffer. Instead we free it (and the ensuing chain) and
-     * recreate it next time round the loop. If we're lucky the hardware
-     * will have already sent the packet, the free will really free, and
-     * there will be zero memory penalty.
-     */
-
-    pbuf_free(rambuf);
-    left -= fragsize;
-    ofo += nfb;
-  }
-  MIB2_STATS_INC(mib2.ipfragoks);
-  return ERR_OK;
-memerr:
-  MIB2_STATS_INC(mib2.ipfragfails);
-  return ERR_MEM;
-}
-#endif /* IP_FRAG */
-
-#endif /* LWIP_IPV4 */

+ 0 - 50
components/net/lwip-2.0.0/src/core/ipv6/dhcp6.c

@@ -1,50 +0,0 @@
-/**
- * @file
- *
- * DHCPv6.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/ip6_addr.h"
-#include "lwip/def.h"
-
-
-#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */

+ 0 - 126
components/net/lwip-2.0.0/src/core/ipv6/ethip6.c

@@ -1,126 +0,0 @@
-/**
- * @file
- *
- * Ethernet output for IPv6. Uses ND tables for link-layer addressing.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV6 && LWIP_ETHERNET
-
-#include "lwip/ethip6.h"
-#include "lwip/nd6.h"
-#include "lwip/pbuf.h"
-#include "lwip/ip6.h"
-#include "lwip/ip6_addr.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/netif.h"
-#include "lwip/icmp6.h"
-#include "lwip/prot/ethernet.h"
-#include "netif/ethernet.h"
-
-#include <string.h>
-
-/**
- * Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
- *
- * For IPv6 multicast, corresponding Ethernet addresses
- * are selected and the packet is transmitted on the link.
- *
- * For unicast addresses, ...
- *
- * @todo anycast addresses
- *
- * @param netif The lwIP network interface which the IP packet will be sent on.
- * @param q The pbuf(s) containing the IP packet to be sent.
- * @param ip6addr The IP address of the packet destination.
- *
- * @return
- * - ERR_RTE No route to destination (no gateway to external networks),
- * or the return type of either nd6_queue_packet() or ethernet_output().
- */
-err_t
-ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
-{
-  struct eth_addr dest;
-  s8_t i;
-
-  /* multicast destination IP address? */
-  if (ip6_addr_ismulticast(ip6addr)) {
-    /* Hash IP multicast address to MAC address.*/
-    dest.addr[0] = 0x33;
-    dest.addr[1] = 0x33;
-    dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0];
-    dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1];
-    dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2];
-    dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
-
-    /* Send out. */
-    return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
-  }
-
-  /* We have a unicast destination IP address */
-  /* @todo anycast? */
-  /* Get next hop record. */
-  i = nd6_get_next_hop_entry(ip6addr, netif);
-  if (i < 0) {
-    /* failed to get a next hop neighbor record. */
-    return ERR_MEM;
-  }
-
-  /* Now that we have a destination record, send or queue the packet. */
-  if (neighbor_cache[i].state == ND6_STALE) {
-    /* Switch to delay state. */
-    neighbor_cache[i].state = ND6_DELAY;
-    neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
-  }
-  /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
-  if ((neighbor_cache[i].state == ND6_REACHABLE) ||
-      (neighbor_cache[i].state == ND6_DELAY) ||
-      (neighbor_cache[i].state == ND6_PROBE)) {
-
-    /* Send out. */
-    SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
-    return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
-  }
-
-  /* We should queue packet on this interface. */
-  return nd6_queue_packet(i, q);
-}
-
-#endif /* LWIP_IPV6 && LWIP_ETHERNET */

+ 0 - 350
components/net/lwip-2.0.0/src/core/ipv6/icmp6.c

@@ -1,350 +0,0 @@
-/**
- * @file
- *
- * IPv6 version of ICMP, as per RFC 4443.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/icmp6.h"
-#include "lwip/prot/icmp6.h"
-#include "lwip/ip6.h"
-#include "lwip/ip6_addr.h"
-#include "lwip/inet_chksum.h"
-#include "lwip/pbuf.h"
-#include "lwip/netif.h"
-#include "lwip/nd6.h"
-#include "lwip/mld6.h"
-#include "lwip/ip.h"
-#include "lwip/stats.h"
-
-#include <string.h>
-
-#ifndef LWIP_ICMP6_DATASIZE
-#define LWIP_ICMP6_DATASIZE   8
-#endif
-#if LWIP_ICMP6_DATASIZE == 0
-#define LWIP_ICMP6_DATASIZE   8
-#endif
-
-/* Forward declarations */
-static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
-
-
-/**
- * Process an input ICMPv6 message. Called by ip6_input.
- *
- * Will generate a reply for echo requests. Other messages are forwarded
- * to nd6_input, or mld6_input.
- *
- * @param p the mld packet, p->payload pointing to the icmpv6 header
- * @param inp the netif on which this packet was received
- */
-void
-icmp6_input(struct pbuf *p, struct netif *inp)
-{
-  struct icmp6_hdr *icmp6hdr;
-  struct pbuf *r;
-  const ip6_addr_t *reply_src;
-
-  ICMP6_STATS_INC(icmp6.recv);
-
-  /* Check that ICMPv6 header fits in payload */
-  if (p->len < sizeof(struct icmp6_hdr)) {
-    /* drop short packets */
-    pbuf_free(p);
-    ICMP6_STATS_INC(icmp6.lenerr);
-    ICMP6_STATS_INC(icmp6.drop);
-    return;
-  }
-
-  icmp6hdr = (struct icmp6_hdr *)p->payload;
-
-#if CHECKSUM_CHECK_ICMP6
-  IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) {
-    if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
-                          ip6_current_dest_addr()) != 0) {
-      /* Checksum failed */
-      pbuf_free(p);
-      ICMP6_STATS_INC(icmp6.chkerr);
-      ICMP6_STATS_INC(icmp6.drop);
-      return;
-    }
-  }
-#endif /* CHECKSUM_CHECK_ICMP6 */
-
-  switch (icmp6hdr->type) {
-  case ICMP6_TYPE_NA: /* Neighbor advertisement */
-  case ICMP6_TYPE_NS: /* Neighbor solicitation */
-  case ICMP6_TYPE_RA: /* Router advertisement */
-  case ICMP6_TYPE_RD: /* Redirect */
-  case ICMP6_TYPE_PTB: /* Packet too big */
-    nd6_input(p, inp);
-    return;
-    break;
-  case ICMP6_TYPE_RS:
-#if LWIP_IPV6_FORWARD
-    /* @todo implement router functionality */
-#endif
-    break;
-#if LWIP_IPV6_MLD
-  case ICMP6_TYPE_MLQ:
-  case ICMP6_TYPE_MLR:
-  case ICMP6_TYPE_MLD:
-    mld6_input(p, inp);
-    return;
-    break;
-#endif
-  case ICMP6_TYPE_EREQ:
-#if !LWIP_MULTICAST_PING
-    /* multicast destination address? */
-    if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
-      /* drop */
-      pbuf_free(p);
-      ICMP6_STATS_INC(icmp6.drop);
-      return;
-    }
-#endif /* LWIP_MULTICAST_PING */
-
-    /* Allocate reply. */
-    r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
-    if (r == NULL) {
-      /* drop */
-      pbuf_free(p);
-      ICMP6_STATS_INC(icmp6.memerr);
-      return;
-    }
-
-    /* Copy echo request. */
-    if (pbuf_copy(r, p) != ERR_OK) {
-      /* drop */
-      pbuf_free(p);
-      pbuf_free(r);
-      ICMP6_STATS_INC(icmp6.err);
-      return;
-    }
-
-    /* Determine reply source IPv6 address. */
-#if LWIP_MULTICAST_PING
-    if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
-      reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr()));
-      if (reply_src == NULL) {
-        /* drop */
-        pbuf_free(p);
-        pbuf_free(r);
-        ICMP6_STATS_INC(icmp6.rterr);
-        return;
-      }
-    }
-    else
-#endif /* LWIP_MULTICAST_PING */
-    {
-      reply_src = ip6_current_dest_addr();
-    }
-
-    /* Set fields in reply. */
-    ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
-    ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
-#if CHECKSUM_GEN_ICMP6
-    IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) {
-      ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
-          IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
-    }
-#endif /* CHECKSUM_GEN_ICMP6 */
-
-    /* Send reply. */
-    ICMP6_STATS_INC(icmp6.xmit);
-    ip6_output_if(r, reply_src, ip6_current_src_addr(),
-        LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
-    pbuf_free(r);
-
-    break;
-  default:
-    ICMP6_STATS_INC(icmp6.proterr);
-    ICMP6_STATS_INC(icmp6.drop);
-    break;
-  }
-
-  pbuf_free(p);
-}
-
-
-/**
- * Send an icmpv6 'destination unreachable' packet.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- *          p->payload pointing to the IPv6 header
- * @param c ICMPv6 code for the unreachable type
- */
-void
-icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
-{
-  icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
-}
-
-/**
- * Send an icmpv6 'packet too big' packet.
- *
- * @param p the input packet for which the 'packet too big' should be sent,
- *          p->payload pointing to the IPv6 header
- * @param mtu the maximum mtu that we can accept
- */
-void
-icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
-{
-  icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
-}
-
-/**
- * Send an icmpv6 'time exceeded' packet.
- *
- * @param p the input packet for which the 'unreachable' should be sent,
- *          p->payload pointing to the IPv6 header
- * @param c ICMPv6 code for the time exceeded type
- */
-void
-icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
-{
-  icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
-}
-
-/**
- * Send an icmpv6 'parameter problem' packet.
- *
- * @param p the input packet for which the 'param problem' should be sent,
- *          p->payload pointing to the IP header
- * @param c ICMPv6 code for the param problem type
- * @param pointer the pointer to the byte where the parameter is found
- */
-void
-icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
-{
-  icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
-}
-
-/**
- * Send an ICMPv6 packet in response to an incoming packet.
- *
- * @param p the input packet for which the response should be sent,
- *          p->payload pointing to the IPv6 header
- * @param code Code of the ICMPv6 header
- * @param data Additional 32-bit parameter in the ICMPv6 header
- * @param type Type of the ICMPv6 header
- */
-static void
-icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
-{
-  struct pbuf *q;
-  struct icmp6_hdr *icmp6hdr;
-  const ip6_addr_t *reply_src;
-  ip6_addr_t *reply_dest;
-  ip6_addr_t reply_src_local, reply_dest_local;
-  struct ip6_hdr *ip6hdr;
-  struct netif *netif;
-
-  /* ICMPv6 header + IPv6 header + data */
-  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
-                 PBUF_RAM);
-  if (q == NULL) {
-    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
-    ICMP6_STATS_INC(icmp6.memerr);
-    return;
-  }
-  LWIP_ASSERT("check that first pbuf can hold icmp 6message",
-             (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
-
-  icmp6hdr = (struct icmp6_hdr *)q->payload;
-  icmp6hdr->type = type;
-  icmp6hdr->code = code;
-  icmp6hdr->data = data;
-
-  /* copy fields from original packet */
-  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
-          IP6_HLEN + LWIP_ICMP6_DATASIZE);
-
-  /* Get the destination address and netif for this ICMP message. */
-  if ((ip_current_netif() == NULL) ||
-      ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) {
-    /* Special case, as ip6_current_xxx is either NULL, or points
-     * to a different packet than the one that expired.
-     * We must use the addresses that are stored in the expired packet. */
-    ip6hdr = (struct ip6_hdr *)p->payload;
-    /* copy from packed address to aligned address */
-    ip6_addr_copy(reply_dest_local, ip6hdr->src);
-    ip6_addr_copy(reply_src_local, ip6hdr->dest);
-    reply_dest = &reply_dest_local;
-    reply_src = &reply_src_local;
-    netif = ip6_route(reply_src, reply_dest);
-    if (netif == NULL) {
-      /* drop */
-      pbuf_free(q);
-      ICMP6_STATS_INC(icmp6.rterr);
-      return;
-    }
-  }
-  else {
-    netif = ip_current_netif();
-    reply_dest = ip6_current_src_addr();
-
-    /* Select an address to use as source. */
-    reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest));
-    if (reply_src == NULL) {
-      /* drop */
-      pbuf_free(q);
-      ICMP6_STATS_INC(icmp6.rterr);
-      return;
-    }
-  }
-
-  /* calculate checksum */
-  icmp6hdr->chksum = 0;
-#if CHECKSUM_GEN_ICMP6
-  IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
-    icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
-      reply_src, reply_dest);
-  }
-#endif /* CHECKSUM_GEN_ICMP6 */
-
-  ICMP6_STATS_INC(icmp6.xmit);
-  ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
-  pbuf_free(q);
-}
-
-#endif /* LWIP_ICMP6 && LWIP_IPV6 */

+ 0 - 53
components/net/lwip-2.0.0/src/core/ipv6/inet6.c

@@ -1,53 +0,0 @@
-/**
- * @file
- *
- * INET v6 addresses.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/def.h"
-#include "lwip/inet.h"
-
-/** This variable is initialized by the system to contain the wildcard IPv6 address.
- */
-const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
-
-#endif /* LWIP_IPV6 */

+ 0 - 1110
components/net/lwip-2.0.0/src/core/ipv6/ip6.c

@@ -1,1110 +0,0 @@
-/**
- * @file
- *
- * IPv6 layer.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/netif.h"
-#include "lwip/ip.h"
-#include "lwip/ip6.h"
-#include "lwip/ip6_addr.h"
-#include "lwip/ip6_frag.h"
-#include "lwip/icmp6.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/priv/tcp_priv.h"
-#include "lwip/dhcp6.h"
-#include "lwip/nd6.h"
-#include "lwip/mld6.h"
-#include "lwip/debug.h"
-#include "lwip/stats.h"
-
-/**
- * Finds the appropriate network interface for a given IPv6 address. It tries to select
- * a netif following a sequence of heuristics:
- * 1) if there is only 1 netif, return it
- * 2) if the destination is a link-local address, try to match the src address to a netif.
- *    this is a tricky case because with multiple netifs, link-local addresses only have
- *    meaning within a particular subnet/link.
- * 3) tries to match the destination subnet to a configured address
- * 4) tries to find a router
- * 5) tries to match the source address to the netif
- * 6) returns the default netif, if configured
- *
- * @param src the source IPv6 address, if known
- * @param dest the destination IPv6 address for which to find the route
- * @return the netif on which to send to reach dest
- */
-struct netif *
-ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
-{
-  struct netif *netif;
-  s8_t i;
-
-  /* If single netif configuration, fast return. */
-  if ((netif_list != NULL) && (netif_list->next == NULL)) {
-    if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) {
-      return NULL;
-    }
-    return netif_list;
-  }
-
-  /* Special processing for link-local addresses. */
-  if (ip6_addr_islinklocal(dest)) {
-    if (ip6_addr_isany(src)) {
-      /* Use default netif, if Up. */
-      if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
-        return NULL;
-      }
-      return netif_default;
-    }
-
-    /* Try to find the netif for the source address, checking that link is up. */
-    for (netif = netif_list; netif != NULL; netif = netif->next) {
-      if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
-        continue;
-      }
-      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-        if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-            ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
-          return netif;
-        }
-      }
-    }
-
-    /* netif not found, use default netif, if up */
-    if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
-      return NULL;
-    }
-    return netif_default;
-  }
-
-  /* we come here for non-link-local addresses */
-#ifdef LWIP_HOOK_IP6_ROUTE
-  netif = LWIP_HOOK_IP6_ROUTE(src, dest);
-  if (netif != NULL) {
-    return netif;
-  }
-#endif
-
-  /* See if the destination subnet matches a configured address. */
-  for (netif = netif_list; netif != NULL; netif = netif->next) {
-    if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
-      continue;
-    }
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
-        return netif;
-      }
-    }
-  }
-
-  /* Get the netif for a suitable router. */
-  i = nd6_select_router(dest, NULL);
-  if (i >= 0) {
-    if (default_router_list[i].neighbor_entry != NULL) {
-      if (default_router_list[i].neighbor_entry->netif != NULL) {
-        if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
-          return default_router_list[i].neighbor_entry->netif;
-        }
-      }
-    }
-  }
-
-  /* try with the netif that matches the source address. */
-  if (!ip6_addr_isany(src)) {
-    for (netif = netif_list; netif != NULL; netif = netif->next) {
-      if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
-        continue;
-      }
-      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-        if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-            ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
-          return netif;
-        }
-      }
-    }
-  }
-
-#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
-  /* loopif is disabled, loopback traffic is passed through any netif */
-  if (ip6_addr_isloopback(dest)) {
-    /* don't check for link on loopback traffic */
-    if (netif_is_up(netif_default)) {
-      return netif_default;
-    }
-    /* default netif is not up, just use any netif for loopback traffic */
-    for (netif = netif_list; netif != NULL; netif = netif->next) {
-      if (netif_is_up(netif)) {
-        return netif;
-      }
-    }
-    return NULL;
-  }
-#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
-
-  /* no matching netif found, use default netif, if up */
-  if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
-    return NULL;
-  }
-  return netif_default;
-}
-
-/**
- * @ingroup ip6
- * Select the best IPv6 source address for a given destination
- * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
- * is assumed.
- *
- * @param netif the netif on which to send a packet
- * @param dest the destination we are trying to reach
- * @return the most suitable source address to use, or NULL if no suitable
- *         source address is found
- */
-const ip_addr_t *
-ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
-{
-  const ip_addr_t *src = NULL;
-  u8_t i;
-
-  /* If dest is link-local, choose a link-local source. */
-  if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) {
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
-        return netif_ip_addr6(netif, i);
-      }
-    }
-  }
-
-  /* Choose a site-local with matching prefix. */
-  if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) {
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_issitelocal(netif_ip6_addr(netif, i)) &&
-          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
-        return netif_ip_addr6(netif, i);
-      }
-    }
-  }
-
-  /* Choose a unique-local with matching prefix. */
-  if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) {
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) &&
-          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
-        return netif_ip_addr6(netif, i);
-      }
-    }
-  }
-
-  /* Choose a global with best matching prefix. */
-  if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) {
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_isglobal(netif_ip6_addr(netif, i))) {
-        if (src == NULL) {
-          src = netif_ip_addr6(netif, i);
-        }
-        else {
-          /* Replace src only if we find a prefix match. */
-          /* @todo find longest matching prefix. */
-          if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) &&
-              ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) {
-            src = netif_ip_addr6(netif, i);
-          }
-        }
-      }
-    }
-    if (src != NULL) {
-      return src;
-    }
-  }
-
-  /* Last resort: see if arbitrary prefix matches. */
-  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-    if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-        ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
-      return netif_ip_addr6(netif, i);
-    }
-  }
-
-  return NULL;
-}
-
-#if LWIP_IPV6_FORWARD
-/**
- * Forwards an IPv6 packet. It finds an appropriate route for the
- * packet, decrements the HL value of the packet, and outputs
- * the packet on the appropriate interface.
- *
- * @param p the packet to forward (p->payload points to IP header)
- * @param iphdr the IPv6 header of the input packet
- * @param inp the netif on which this packet was received
- */
-static void
-ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
-{
-  struct netif *netif;
-
-  /* do not forward link-local addresses */
-  if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
-    IP6_STATS_INC(ip6.rterr);
-    IP6_STATS_INC(ip6.drop);
-    return;
-  }
-
-  /* Find network interface where to forward this IP packet to. */
-  netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
-  if (netif == NULL) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
-        IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
-        IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
-#if LWIP_ICMP6
-    /* Don't send ICMP messages in response to ICMP messages */
-    if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
-      icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
-    }
-#endif /* LWIP_ICMP6 */
-    IP6_STATS_INC(ip6.rterr);
-    IP6_STATS_INC(ip6.drop);
-    return;
-  }
-  /* Do not forward packets onto the same network interface on which
-   * they arrived. */
-  if (netif == inp) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
-    IP6_STATS_INC(ip6.rterr);
-    IP6_STATS_INC(ip6.drop);
-    return;
-  }
-
-  /* decrement HL */
-  IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
-  /* send ICMP6 if HL == 0 */
-  if (IP6H_HOPLIM(iphdr) == 0) {
-#if LWIP_ICMP6
-    /* Don't send ICMP messages in response to ICMP messages */
-    if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
-      icmp6_time_exceeded(p, ICMP6_TE_HL);
-    }
-#endif /* LWIP_ICMP6 */
-    IP6_STATS_INC(ip6.drop);
-    return;
-  }
-
-  if (netif->mtu && (p->tot_len > netif->mtu)) {
-#if LWIP_ICMP6
-    /* Don't send ICMP messages in response to ICMP messages */
-    if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
-      icmp6_packet_too_big(p, netif->mtu);
-    }
-#endif /* LWIP_ICMP6 */
-    IP6_STATS_INC(ip6.drop);
-    return;
-  }
-
-  LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
-      IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
-      IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
-
-  /* transmit pbuf on chosen interface */
-  netif->output_ip6(netif, p, ip6_current_dest_addr());
-  IP6_STATS_INC(ip6.fw);
-  IP6_STATS_INC(ip6.xmit);
-  return;
-}
-#endif /* LWIP_IPV6_FORWARD */
-
-/**
- * This function is called by the network interface device driver when
- * an IPv6 packet is received. The function does the basic checks of the
- * IP header such as packet size being at least larger than the header
- * size etc. If the packet was not destined for us, the packet is
- * forwarded (using ip6_forward).
- *
- * Finally, the packet is sent to the upper layer protocol input function.
- *
- * @param p the received IPv6 packet (p->payload points to IPv6 header)
- * @param inp the netif on which this packet was received
- * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
- *         processed, but currently always returns ERR_OK)
- */
-err_t
-ip6_input(struct pbuf *p, struct netif *inp)
-{
-  struct ip6_hdr *ip6hdr;
-  struct netif *netif;
-  u8_t nexth;
-  u16_t hlen; /* the current header length */
-  u8_t i;
-#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/
-  @todo
-  int check_ip_src=1;
-#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
-
-  IP6_STATS_INC(ip6.recv);
-
-  /* identify the IP header */
-  ip6hdr = (struct ip6_hdr *)p->payload;
-  if (IP6H_V(ip6hdr) != 6) {
-    LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
-        IP6H_V(ip6hdr)));
-    pbuf_free(p);
-    IP6_STATS_INC(ip6.err);
-    IP6_STATS_INC(ip6.drop);
-    return ERR_OK;
-  }
-
-#ifdef LWIP_HOOK_IP6_INPUT
-  if (LWIP_HOOK_IP6_INPUT(p, inp)) {
-    /* the packet has been eaten */
-    return ERR_OK;
-  }
-#endif
-
-  /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
-  if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) {
-    if (IP6_HLEN > p->len) {
-      LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
-            (u16_t)IP6_HLEN, p->len));
-    }
-    if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
-      LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-        ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
-            (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
-    }
-    /* free (drop) packet pbufs */
-    pbuf_free(p);
-    IP6_STATS_INC(ip6.lenerr);
-    IP6_STATS_INC(ip6.drop);
-    return ERR_OK;
-  }
-
-  /* Trim pbuf. This should have been done at the netif layer,
-   * but we'll do it anyway just to be sure that its done. */
-  pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr));
-
-  /* copy IP addresses to aligned ip6_addr_t */
-  ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
-  ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
-
-  /* Don't accept virtual IPv6 mapped IPv4 addresses */
-  if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
-     ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src))     ) {
-    IP6_STATS_INC(ip6.err);
-    IP6_STATS_INC(ip6.drop);
-    return ERR_OK;
-  }
-
-  /* current header pointer. */
-  ip_data.current_ip6_header = ip6hdr;
-
-  /* In netif, used in case we need to send ICMPv6 packets back. */
-  ip_data.current_netif = inp;
-  ip_data.current_input_netif = inp;
-
-  /* match packet against an interface, i.e. is this packet for us? */
-  if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
-    /* Always joined to multicast if-local and link-local all-nodes group. */
-    if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
-        ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) {
-      netif = inp;
-    }
-#if LWIP_IPV6_MLD
-    else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) {
-      netif = inp;
-    }
-#else /* LWIP_IPV6_MLD */
-    else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
-      /* Filter solicited node packets when MLD is not enabled
-       * (for Neighbor discovery). */
-      netif = NULL;
-      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-        if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) &&
-            ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
-          netif = inp;
-          LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
-              netif->name[0], netif->name[1]));
-          break;
-        }
-      }
-    }
-#endif /* LWIP_IPV6_MLD */
-    else {
-      netif = NULL;
-    }
-  } else {
-    /* start trying with inp. if that's not acceptable, start walking the
-       list of configured netifs.
-       'first' is used as a boolean to mark whether we started walking the list */
-    int first = 1;
-    netif = inp;
-    do {
-      /* interface is up? */
-      if (netif_is_up(netif)) {
-        /* unicast to this interface address? address configured? */
-        for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-          if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-              ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) {
-            /* exit outer loop */
-            goto netif_found;
-          }
-        }
-      }
-      if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
-        /* Do not match link-local addresses to other netifs. */
-        netif = NULL;
-        break;
-      }
-      if (first) {
-        first = 0;
-        netif = netif_list;
-      } else {
-        netif = netif->next;
-      }
-      if (netif == inp) {
-        netif = netif->next;
-      }
-    } while (netif != NULL);
-netif_found:
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n",
-        netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X'));
-  }
-
-  /* "::" packet source address? (used in duplicate address detection) */
-  if (ip6_addr_isany(ip6_current_src_addr()) &&
-      (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
-    /* packet source is not valid */
-    /* free (drop) packet pbufs */
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
-    pbuf_free(p);
-    IP6_STATS_INC(ip6.drop);
-    goto ip6_input_cleanup;
-  }
-
-  /* packet not for us? */
-  if (netif == NULL) {
-    /* packet not for us, route or discard */
-    LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
-#if LWIP_IPV6_FORWARD
-    /* non-multicast packet? */
-    if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
-      /* try to forward IP packet on (other) interfaces */
-      ip6_forward(p, ip6hdr, inp);
-    }
-#endif /* LWIP_IPV6_FORWARD */
-    pbuf_free(p);
-    goto ip6_input_cleanup;
-  }
-
-  /* current netif pointer. */
-  ip_data.current_netif = netif;
-
-  /* Save next header type. */
-  nexth = IP6H_NEXTH(ip6hdr);
-
-  /* Init header length. */
-  hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
-
-  /* Move to payload. */
-  pbuf_header(p, -IP6_HLEN);
-
-  /* Process known option extension headers, if present. */
-  while (nexth != IP6_NEXTH_NONE)
-  {
-    switch (nexth) {
-    case IP6_NEXTH_HOPBYHOP:
-      LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
-      /* Get next header type. */
-      nexth = *((u8_t *)p->payload);
-
-      /* Get the header length. */
-      hlen = 8 * (1 + *((u8_t *)p->payload + 1));
-      ip_data.current_ip_header_tot_len += hlen;
-
-      /* Skip over this header. */
-      if (hlen > p->len) {
-        LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-          ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
-              hlen, p->len));
-        /* free (drop) packet pbufs */
-        pbuf_free(p);
-        IP6_STATS_INC(ip6.lenerr);
-        IP6_STATS_INC(ip6.drop);
-        goto ip6_input_cleanup;
-      }
-
-      pbuf_header(p, -(s16_t)hlen);
-      break;
-    case IP6_NEXTH_DESTOPTS:
-      LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
-      /* Get next header type. */
-      nexth = *((u8_t *)p->payload);
-
-      /* Get the header length. */
-      hlen = 8 * (1 + *((u8_t *)p->payload + 1));
-      ip_data.current_ip_header_tot_len += hlen;
-
-      /* Skip over this header. */
-      if (hlen > p->len) {
-        LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-          ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
-              hlen, p->len));
-        /* free (drop) packet pbufs */
-        pbuf_free(p);
-        IP6_STATS_INC(ip6.lenerr);
-        IP6_STATS_INC(ip6.drop);
-        goto ip6_input_cleanup;
-      }
-
-      pbuf_header(p, -(s16_t)hlen);
-      break;
-    case IP6_NEXTH_ROUTING:
-      LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
-      /* Get next header type. */
-      nexth = *((u8_t *)p->payload);
-
-      /* Get the header length. */
-      hlen = 8 * (1 + *((u8_t *)p->payload + 1));
-      ip_data.current_ip_header_tot_len += hlen;
-
-      /* Skip over this header. */
-      if (hlen > p->len) {
-        LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-          ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
-              hlen, p->len));
-        /* free (drop) packet pbufs */
-        pbuf_free(p);
-        IP6_STATS_INC(ip6.lenerr);
-        IP6_STATS_INC(ip6.drop);
-        goto ip6_input_cleanup;
-      }
-
-      pbuf_header(p, -(s16_t)hlen);
-      break;
-
-    case IP6_NEXTH_FRAGMENT:
-    {
-      struct ip6_frag_hdr *frag_hdr;
-      LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
-
-      frag_hdr = (struct ip6_frag_hdr *)p->payload;
-
-      /* Get next header type. */
-      nexth = frag_hdr->_nexth;
-
-      /* Fragment Header length. */
-      hlen = 8;
-      ip_data.current_ip_header_tot_len += hlen;
-
-      /* Make sure this header fits in current pbuf. */
-      if (hlen > p->len) {
-        LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
-          ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
-              hlen, p->len));
-        /* free (drop) packet pbufs */
-        pbuf_free(p);
-        IP6_FRAG_STATS_INC(ip6_frag.lenerr);
-        IP6_FRAG_STATS_INC(ip6_frag.drop);
-        goto ip6_input_cleanup;
-      }
-
-      /* Offset == 0 and more_fragments == 0? */
-      if ((frag_hdr->_fragment_offset &
-           PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
-        /* This is a 1-fragment packet, usually a packet that we have
-         * already reassembled. Skip this header anc continue. */
-        pbuf_header(p, -(s16_t)hlen);
-      } else {
-#if LWIP_IPV6_REASS
-
-        /* reassemble the packet */
-        p = ip6_reass(p);
-        /* packet not fully reassembled yet? */
-        if (p == NULL) {
-          goto ip6_input_cleanup;
-        }
-
-        /* Returned p point to IPv6 header.
-         * Update all our variables and pointers and continue. */
-        ip6hdr = (struct ip6_hdr *)p->payload;
-        nexth = IP6H_NEXTH(ip6hdr);
-        hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
-        pbuf_header(p, -IP6_HLEN);
-
-#else /* LWIP_IPV6_REASS */
-        /* free (drop) packet pbufs */
-        LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
-        pbuf_free(p);
-        IP6_STATS_INC(ip6.opterr);
-        IP6_STATS_INC(ip6.drop);
-        goto ip6_input_cleanup;
-#endif /* LWIP_IPV6_REASS */
-      }
-      break;
-    }
-    default:
-      goto options_done;
-      break;
-    }
-  }
-options_done:
-
-  /* p points to IPv6 header again. */
-  pbuf_header_force(p, ip_data.current_ip_header_tot_len);
-
-  /* send to upper layers */
-  LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
-  ip6_debug_print(p);
-  LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
-
-#if LWIP_RAW
-  /* raw input did not eat the packet? */
-  if (raw_input(p, inp) == 0)
-#endif /* LWIP_RAW */
-  {
-    switch (nexth) {
-    case IP6_NEXTH_NONE:
-      pbuf_free(p);
-      break;
-#if LWIP_UDP
-    case IP6_NEXTH_UDP:
-#if LWIP_UDPLITE
-    case IP6_NEXTH_UDPLITE:
-#endif /* LWIP_UDPLITE */
-      /* Point to payload. */
-      pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
-      udp_input(p, inp);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-    case IP6_NEXTH_TCP:
-      /* Point to payload. */
-      pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
-      tcp_input(p, inp);
-      break;
-#endif /* LWIP_TCP */
-#if LWIP_ICMP6
-    case IP6_NEXTH_ICMP6:
-      /* Point to payload. */
-      pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
-      icmp6_input(p, inp);
-      break;
-#endif /* LWIP_ICMP */
-    default:
-#if LWIP_ICMP6
-      /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
-      if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
-          (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
-        icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen);
-      }
-#endif /* LWIP_ICMP */
-      LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
-      pbuf_free(p);
-      IP6_STATS_INC(ip6.proterr);
-      IP6_STATS_INC(ip6.drop);
-      break;
-    }
-  }
-
-ip6_input_cleanup:
-  ip_data.current_netif = NULL;
-  ip_data.current_input_netif = NULL;
-  ip_data.current_ip6_header = NULL;
-  ip_data.current_ip_header_tot_len = 0;
-  ip6_addr_set_zero(ip6_current_src_addr());
-  ip6_addr_set_zero(ip6_current_dest_addr());
-
-  return ERR_OK;
-}
-
-
-/**
- * Sends an IPv6 packet on a network interface. This function constructs
- * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
- * used as source (usually during network startup). If the source IPv6 address it
- * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
- * interface is filled in as source address. If the destination IPv6 address is
- * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
- * p->payload points to it instead of the data.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IPv6 header and p->payload points to that IPv6 header)
- * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
- *         IP address of the netif is selected and used as source address.
- *         if src == NULL, IP6_ADDR_ANY is used as source)
- * @param dest the destination IPv6 address to send the packet to
- * @param hl the Hop Limit value to be set in the IPv6 header
- * @param tc the Traffic Class value to be set in the IPv6 header
- * @param nexth the Next Header to be set in the IPv6 header
- * @param netif the netif on which to send this packet
- * @return ERR_OK if the packet was sent OK
- *         ERR_BUF if p doesn't have enough space for IPv6/LINK headers
- *         returns errors returned by netif->output
- */
-err_t
-ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
-             u8_t hl, u8_t tc,
-             u8_t nexth, struct netif *netif)
-{
-  const ip6_addr_t *src_used = src;
-  if (dest != LWIP_IP_HDRINCL) {
-    if (src != NULL && ip6_addr_isany(src)) {
-      src = ip_2_ip6(ip6_select_source_address(netif, dest));
-      if ((src == NULL) || ip6_addr_isany(src)) {
-        /* No appropriate source address was found for this packet. */
-        LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
-        IP6_STATS_INC(ip6.rterr);
-        return ERR_RTE;
-      }
-    }
-  }
-  return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
-}
-
-/**
- * Same as ip6_output_if() but 'src' address is not replaced by netif address
- * when it is 'any'.
- */
-err_t
-ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
-             u8_t hl, u8_t tc,
-             u8_t nexth, struct netif *netif)
-{
-  struct ip6_hdr *ip6hdr;
-  ip6_addr_t dest_addr;
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  /* Should the IPv6 header be generated or is it already included in p? */
-  if (dest != LWIP_IP_HDRINCL) {
-    /* generate IPv6 header */
-    if (pbuf_header(p, IP6_HLEN)) {
-      LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
-      IP6_STATS_INC(ip6.err);
-      return ERR_BUF;
-    }
-
-    ip6hdr = (struct ip6_hdr *)p->payload;
-    LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
-               (p->len >= sizeof(struct ip6_hdr)));
-
-    IP6H_HOPLIM_SET(ip6hdr, hl);
-    IP6H_NEXTH_SET(ip6hdr, nexth);
-
-    /* dest cannot be NULL here */
-    ip6_addr_copy(ip6hdr->dest, *dest);
-
-    IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
-    IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN);
-
-    if (src == NULL) {
-      src = IP6_ADDR_ANY6;
-    }
-    /* src cannot be NULL here */
-    ip6_addr_copy(ip6hdr->src, *src);
-
-  } else {
-    /* IP header already included in p */
-    ip6hdr = (struct ip6_hdr *)p->payload;
-    ip6_addr_copy(dest_addr, ip6hdr->dest);
-    dest = &dest_addr;
-  }
-
-  IP6_STATS_INC(ip6.xmit);
-
-  LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
-  ip6_debug_print(p);
-
-#if ENABLE_LOOPBACK
-  {
-    int i;
-#if !LWIP_HAVE_LOOPIF
-    if (ip6_addr_isloopback(dest)) {
-      return netif_loop_output(netif, p);
-    }
-#endif /* !LWIP_HAVE_LOOPIF */
-    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
-          ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) {
-        /* Packet to self, enqueue it for loopback */
-        LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
-        return netif_loop_output(netif, p);
-      }
-    }
-  }
-#endif /* ENABLE_LOOPBACK */
-#if LWIP_IPV6_FRAG
-  /* don't fragment if interface has mtu set to 0 [loopif] */
-  if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
-    return ip6_frag(p, netif, dest);
-  }
-#endif /* LWIP_IPV6_FRAG */
-
-  LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
-  return netif->output_ip6(netif, p, dest);
-}
-
-/**
- * Simple interface to ip6_output_if. It finds the outgoing network
- * interface and calls upon ip6_output_if to do the actual work.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IPv6 header and p->payload points to that IPv6 header)
- * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
- *         IP address of the netif is selected and used as source address.
- *         if src == NULL, IP6_ADDR_ANY is used as source)
- * @param dest the destination IPv6 address to send the packet to
- * @param hl the Hop Limit value to be set in the IPv6 header
- * @param tc the Traffic Class value to be set in the IPv6 header
- * @param nexth the Next Header to be set in the IPv6 header
- *
- * @return ERR_RTE if no route is found
- *         see ip_output_if() for more return values
- */
-err_t
-ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
-          u8_t hl, u8_t tc, u8_t nexth)
-{
-  struct netif *netif;
-  struct ip6_hdr *ip6hdr;
-  ip6_addr_t src_addr, dest_addr;
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  if (dest != LWIP_IP_HDRINCL) {
-    netif = ip6_route(src, dest);
-  } else {
-    /* IP header included in p, read addresses. */
-    ip6hdr = (struct ip6_hdr *)p->payload;
-    ip6_addr_copy(src_addr, ip6hdr->src);
-    ip6_addr_copy(dest_addr, ip6hdr->dest);
-    netif = ip6_route(&src_addr, &dest_addr);
-  }
-
-  if (netif == NULL) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
-        IP6_ADDR_BLOCK1(dest),
-        IP6_ADDR_BLOCK2(dest),
-        IP6_ADDR_BLOCK3(dest),
-        IP6_ADDR_BLOCK4(dest),
-        IP6_ADDR_BLOCK5(dest),
-        IP6_ADDR_BLOCK6(dest),
-        IP6_ADDR_BLOCK7(dest),
-        IP6_ADDR_BLOCK8(dest)));
-    IP6_STATS_INC(ip6.rterr);
-    return ERR_RTE;
-  }
-
-  return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
-}
-
-
-#if LWIP_NETIF_HWADDRHINT
-/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
- *  before calling ip6_output_if.
- *
- * @param p the packet to send (p->payload points to the data, e.g. next
-            protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
-            IPv6 header and p->payload points to that IPv6 header)
- * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
- *         IP address of the netif is selected and used as source address.
- *         if src == NULL, IP6_ADDR_ANY is used as source)
- * @param dest the destination IPv6 address to send the packet to
- * @param hl the Hop Limit value to be set in the IPv6 header
- * @param tc the Traffic Class value to be set in the IPv6 header
- * @param nexth the Next Header to be set in the IPv6 header
- * @param addr_hint address hint pointer set to netif->addr_hint before
- *        calling ip_output_if()
- *
- * @return ERR_RTE if no route is found
- *         see ip_output_if() for more return values
- */
-err_t
-ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
-          u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint)
-{
-  struct netif *netif;
-  struct ip6_hdr *ip6hdr;
-  ip6_addr_t src_addr, dest_addr;
-  err_t err;
-
-  LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
-
-  if (dest != LWIP_IP_HDRINCL) {
-    netif = ip6_route(src, dest);
-  } else {
-    /* IP header included in p, read addresses. */
-    ip6hdr = (struct ip6_hdr *)p->payload;
-    ip6_addr_copy(src_addr, ip6hdr->src);
-    ip6_addr_copy(dest_addr, ip6hdr->dest);
-    netif = ip6_route(&src_addr, &dest_addr);
-  }
-
-  if (netif == NULL) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
-        IP6_ADDR_BLOCK1(dest),
-        IP6_ADDR_BLOCK2(dest),
-        IP6_ADDR_BLOCK3(dest),
-        IP6_ADDR_BLOCK4(dest),
-        IP6_ADDR_BLOCK5(dest),
-        IP6_ADDR_BLOCK6(dest),
-        IP6_ADDR_BLOCK7(dest),
-        IP6_ADDR_BLOCK8(dest)));
-    IP6_STATS_INC(ip6.rterr);
-    return ERR_RTE;
-  }
-
-  NETIF_SET_HWADDRHINT(netif, addr_hint);
-  err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
-  NETIF_SET_HWADDRHINT(netif, NULL);
-
-  return err;
-}
-#endif /* LWIP_NETIF_HWADDRHINT*/
-
-#if LWIP_IPV6_MLD
-/**
- * Add a hop-by-hop options header with a router alert option and padding.
- *
- * Used by MLD when sending a Multicast listener report/done message.
- *
- * @param p the packet to which we will prepend the options header
- * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
- * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
- * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
- */
-err_t
-ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
-{
-  struct ip6_hbh_hdr *hbh_hdr;
-
-  /* Move pointer to make room for hop-by-hop options header. */
-  if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) {
-    LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
-    IP6_STATS_INC(ip6.err);
-    return ERR_BUF;
-  }
-
-  hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
-
-  /* Set fields. */
-  hbh_hdr->_nexth = nexth;
-  hbh_hdr->_hlen = 0;
-  hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION;
-  hbh_hdr->_ra_opt_dlen = 2;
-  hbh_hdr->_ra_opt_data = value;
-  hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION;
-  hbh_hdr->_padn_opt_dlen = 0;
-
-  return ERR_OK;
-}
-#endif /* LWIP_IPV6_MLD */
-
-#if IP6_DEBUG
-/* Print an IPv6 header by using LWIP_DEBUGF
- * @param p an IPv6 packet, p->payload pointing to the IPv6 header
- */
-void
-ip6_debug_print(struct pbuf *p)
-{
-  struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
-
-  LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
-  LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" |  %3"U16_F"  |      %7"U32_F"     | (ver, class, flow)\n",
-                    IP6H_V(ip6hdr),
-                    IP6H_TC(ip6hdr),
-                    IP6H_FL(ip6hdr)));
-  LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP6_DEBUG, ("|     %5"U16_F"     |  %3"U16_F"  |  %3"U16_F"  | (plen, nexth, hopl)\n",
-                    IP6H_PLEN(ip6hdr),
-                    IP6H_NEXTH(ip6hdr),
-                    IP6H_HOPLIM(ip6hdr)));
-  LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (src)\n",
-                    IP6_ADDR_BLOCK1(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK2(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK3(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK4(&(ip6hdr->src))));
-  LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
-                    IP6_ADDR_BLOCK5(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK6(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK7(&(ip6hdr->src)),
-                    IP6_ADDR_BLOCK8(&(ip6hdr->src))));
-  LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
-  LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (dest)\n",
-                    IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
-  LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
-                    IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
-                    IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
-  LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
-}
-#endif /* IP6_DEBUG */
-
-#endif /* LWIP_IPV6 */

+ 0 - 292
components/net/lwip-2.0.0/src/core/ipv6/ip6_addr.c

@@ -1,292 +0,0 @@
-/**
- * @file
- *
- * IPv6 addresses.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- * Functions for handling IPv6 addresses.
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/ip_addr.h"
-#include "lwip/def.h"
-
-/* used by IP6_ADDR_ANY(6) in ip6_addr.h */
-const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul);
-
-#ifndef isprint
-#define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
-#define isprint(c)           in_range(c, 0x20, 0x7f)
-#define isdigit(c)           in_range(c, '0', '9')
-#define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
-#define islower(c)           in_range(c, 'a', 'z')
-#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#define xchar(i)             ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
-#endif
-
-/**
- * Check whether "cp" is a valid ascii representation
- * of an IPv6 address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- *
- * @param cp IPv6 address in ascii representation (e.g. "FF01::1")
- * @param addr pointer to which to save the ip address in network order
- * @return 1 if cp could be converted to addr, 0 on failure
- */
-int
-ip6addr_aton(const char *cp, ip6_addr_t *addr)
-{
-  u32_t addr_index, zero_blocks, current_block_index, current_block_value;
-  const char *s;
-
-  /* Count the number of colons, to count the number of blocks in a "::" sequence
-     zero_blocks may be 1 even if there are no :: sequences */
-  zero_blocks = 8;
-  for (s = cp; *s != 0; s++) {
-    if (*s == ':') {
-      zero_blocks--;
-    } else if (!isxdigit(*s)) {
-      break;
-    }
-  }
-
-  /* parse each block */
-  addr_index = 0;
-  current_block_index = 0;
-  current_block_value = 0;
-  for (s = cp; *s != 0; s++) {
-    if (*s == ':') {
-      if (addr) {
-        if (current_block_index & 0x1) {
-          addr->addr[addr_index++] |= current_block_value;
-        }
-        else {
-          addr->addr[addr_index] = current_block_value << 16;
-        }
-      }
-      current_block_index++;
-      current_block_value = 0;
-      if (current_block_index > 7) {
-        /* address too long! */
-        return 0;
-      }
-      if (s[1] == ':') {
-        if (s[2] == ':') {
-          /* invalid format: three successive colons */
-          return 0;
-        }
-        s++;
-        /* "::" found, set zeros */
-        while (zero_blocks > 0) {
-          zero_blocks--;
-          if (current_block_index & 0x1) {
-            addr_index++;
-          } else {
-            if (addr) {
-              addr->addr[addr_index] = 0;
-            }
-          }
-          current_block_index++;
-          if (current_block_index > 7) {
-            /* address too long! */
-            return 0;
-          }
-        }
-      }
-    } else if (isxdigit(*s)) {
-      /* add current digit */
-      current_block_value = (current_block_value << 4) +
-          (isdigit(*s) ? *s - '0' :
-          10 + (islower(*s) ? *s - 'a' : *s - 'A'));
-    } else {
-      /* unexpected digit, space? CRLF? */
-      break;
-    }
-  }
-
-  if (addr) {
-    if (current_block_index & 0x1) {
-      addr->addr[addr_index++] |= current_block_value;
-    }
-    else {
-      addr->addr[addr_index] = current_block_value << 16;
-    }
-  }
-
-  /* convert to network byte order. */
-  if (addr) {
-    for (addr_index = 0; addr_index < 4; addr_index++) {
-      addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]);
-    }
-  }
-
-  if (current_block_index != 7) {
-    return 0;
-  }
-
-  return 1;
-}
-
-/**
- * Convert numeric IPv6 address into ASCII representation.
- * returns ptr to static buffer; not reentrant!
- *
- * @param addr ip6 address in network order to convert
- * @return pointer to a global static (!) buffer that holds the ASCII
- *         representation of addr
- */
-char *
-ip6addr_ntoa(const ip6_addr_t *addr)
-{
-  static char str[40];
-  return ip6addr_ntoa_r(addr, str, 40);
-}
-
-/**
- * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
- *
- * @param addr ip6 address in network order to convert
- * @param buf target buffer where the string is stored
- * @param buflen length of buf
- * @return either pointer to buf which now holds the ASCII
- *         representation of addr or NULL if buf was too small
- */
-char *
-ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
-{
-  u32_t current_block_index, current_block_value, next_block_value;
-  s32_t i;
-  u8_t zero_flag, empty_block_flag;
-
-  i = 0;
-  empty_block_flag = 0; /* used to indicate a zero chain for "::' */
-
-  for (current_block_index = 0; current_block_index < 8; current_block_index++) {
-    /* get the current 16-bit block */
-    current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]);
-    if ((current_block_index & 0x1) == 0) {
-      current_block_value = current_block_value >> 16;
-    }
-    current_block_value &= 0xffff;
-
-    /* Check for empty block. */
-    if (current_block_value == 0) {
-      if (current_block_index == 7 && empty_block_flag == 1) {
-        /* special case, we must render a ':' for the last block. */
-        buf[i++] = ':';
-        if (i >= buflen) {
-          return NULL;
-        }
-        break;
-      }
-      if (empty_block_flag == 0) {
-        /* generate empty block "::", but only if more than one contiguous zero block,
-         * according to current formatting suggestions RFC 5952. */
-        next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]);
-        if ((current_block_index & 0x1) == 0x01) {
-            next_block_value = next_block_value >> 16;
-        }
-        next_block_value &= 0xffff;
-        if (next_block_value == 0) {
-          empty_block_flag = 1;
-          buf[i++] = ':';
-          if (i >= buflen) {
-            return NULL;
-          }
-          continue; /* move on to next block. */
-        }
-      } else if (empty_block_flag == 1) {
-        /* move on to next block. */
-        continue;
-      }
-    } else if (empty_block_flag == 1) {
-      /* Set this flag value so we don't produce multiple empty blocks. */
-      empty_block_flag = 2;
-    }
-
-    if (current_block_index > 0) {
-      buf[i++] = ':';
-      if (i >= buflen) {
-        return NULL;
-      }
-    }
-
-    if ((current_block_value & 0xf000) == 0) {
-      zero_flag = 1;
-    } else {
-      buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
-      zero_flag = 0;
-      if (i >= buflen) {
-        return NULL;
-      }
-    }
-
-    if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
-      /* do nothing */
-    } else {
-      buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
-      zero_flag = 0;
-      if (i >= buflen) {
-        return NULL;
-      }
-    }
-
-    if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
-      /* do nothing */
-    }
-    else {
-      buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
-      zero_flag = 0;
-      if (i >= buflen) {
-        return NULL;
-      }
-    }
-
-    buf[i++] = xchar((current_block_value & 0xf));
-    if (i >= buflen) {
-      return NULL;
-    }
-  }
-
-  buf[i] = 0;
-
-  return buf;
-}
-
-#endif /* LWIP_IPV6 */

+ 0 - 777
components/net/lwip-2.0.0/src/core/ipv6/ip6_frag.c

@@ -1,777 +0,0 @@
-/**
- * @file
- *
- * IPv6 fragmentation and reassembly.
- */
-
-/*
- * Copyright (c) 2010 Inico Technologies Ltd.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Ivan Delamer <delamer@inicotech.com>
- *
- *
- * Please coordinate changes and requests with Ivan Delamer
- * <delamer@inicotech.com>
- */
-
-#include "lwip/opt.h"
-#include "lwip/ip6_frag.h"
-#include "lwip/ip6.h"
-#include "lwip/icmp6.h"
-#include "lwip/nd6.h"
-#include "lwip/ip.h"
-
-#include "lwip/pbuf.h"
-#include "lwip/memp.h"
-#include "lwip/stats.h"
-
-#include <string.h>
-
-#if LWIP_IPV6 && LWIP_IPV6_REASS  /* don't build if not configured for use in lwipopts.h */
-
-
-/** Setting this to 0, you can turn off checking the fragments for overlapping
- * regions. The code gets a little smaller. Only use this if you know that
- * overlapping won't occur on your network! */
-#ifndef IP_REASS_CHECK_OVERLAP
-#define IP_REASS_CHECK_OVERLAP 1
-#endif /* IP_REASS_CHECK_OVERLAP */
-
-/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
- * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
- * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
- * is set to 1, so one datagram can be reassembled at a time, only. */
-#ifndef IP_REASS_FREE_OLDEST
-#define IP_REASS_FREE_OLDEST 1
-#endif /* IP_REASS_FREE_OLDEST */
-
-#if IPV6_FRAG_COPYHEADER
-#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN))
-#endif
-
-#define IP_REASS_FLAG_LASTFRAG 0x01
-
-/** This is a helper struct which holds the starting
- * offset and the ending offset of this fragment to
- * easily chain the fragments.
- * It has the same packing requirements as the IPv6 header, since it replaces
- * the Fragment Header in memory in incoming fragments to keep
- * track of the various fragments.
- */
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct ip6_reass_helper {
-  PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
-  PACK_STRUCT_FIELD(u16_t start);
-  PACK_STRUCT_FIELD(u16_t end);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
-
-/* static variables */
-static struct ip6_reassdata *reassdatagrams;
-static u16_t ip6_reass_pbufcount;
-
-/* Forward declarations. */
-static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr);
-#if IP_REASS_FREE_OLDEST
-static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed);
-#endif /* IP_REASS_FREE_OLDEST */
-
-void
-ip6_reass_tmr(void)
-{
-  struct ip6_reassdata *r, *tmp;
-
-#if !IPV6_FRAG_COPYHEADER
-  LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
-    sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN);
-#endif /* !IPV6_FRAG_COPYHEADER */
-
-  r = reassdatagrams;
-  while (r != NULL) {
-    /* Decrement the timer. Once it reaches 0,
-     * clean up the incomplete fragment assembly */
-    if (r->timer > 0) {
-      r->timer--;
-      r = r->next;
-    } else {
-      /* reassembly timed out */
-      tmp = r;
-      /* get the next pointer before freeing */
-      r = r->next;
-      /* free the helper struct and all enqueued pbufs */
-      ip6_reass_free_complete_datagram(tmp);
-     }
-   }
-}
-
-/**
- * Free a datagram (struct ip6_reassdata) and all its pbufs.
- * Updates the total count of enqueued pbufs (ip6_reass_pbufcount),
- * sends an ICMP time exceeded packet.
- *
- * @param ipr datagram to free
- */
-static void
-ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
-{
-  struct ip6_reassdata *prev;
-  u16_t pbufs_freed = 0;
-  u16_t clen;
-  struct pbuf *p;
-  struct ip6_reass_helper *iprh;
-
-#if LWIP_ICMP6
-  iprh = (struct ip6_reass_helper *)ipr->p->payload;
-  if (iprh->start == 0) {
-    /* The first fragment was received, send ICMP time exceeded. */
-    /* First, de-queue the first pbuf from r->p. */
-    p = ipr->p;
-    ipr->p = iprh->next_pbuf;
-    /* Then, move back to the original ipv6 header (we are now pointing to Fragment header).
-       This cannot fail since we already checked when receiving this fragment. */
-    if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) {
-      LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0);
-    }
-    else {
-      icmp6_time_exceeded(p, ICMP6_TE_FRAG);
-    }
-    clen = pbuf_clen(p);
-    LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
-    pbufs_freed += clen;
-    pbuf_free(p);
-  }
-#endif /* LWIP_ICMP6 */
-
-  /* First, free all received pbufs.  The individual pbufs need to be released
-     separately as they have not yet been chained */
-  p = ipr->p;
-  while (p != NULL) {
-    struct pbuf *pcur;
-    iprh = (struct ip6_reass_helper *)p->payload;
-    pcur = p;
-    /* get the next pointer before freeing */
-    p = iprh->next_pbuf;
-    clen = pbuf_clen(pcur);
-    LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
-    pbufs_freed += clen;
-    pbuf_free(pcur);
-  }
-
-  /* Then, unchain the struct ip6_reassdata from the list and free it. */
-  if (ipr == reassdatagrams) {
-    reassdatagrams = ipr->next;
-  } else {
-    prev = reassdatagrams;
-    while (prev != NULL) {
-      if (prev->next == ipr) {
-        break;
-      }
-      prev = prev->next;
-    }
-    if (prev != NULL) {
-      prev->next = ipr->next;
-    }
-  }
-  memp_free(MEMP_IP6_REASSDATA, ipr);
-
-  /* Finally, update number of pbufs in reassembly queue */
-  LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
-  ip6_reass_pbufcount -= pbufs_freed;
-}
-
-#if IP_REASS_FREE_OLDEST
-/**
- * Free the oldest datagram to make room for enqueueing new fragments.
- * The datagram ipr is not freed!
- *
- * @param ipr ip6_reassdata for the current fragment
- * @param pbufs_needed number of pbufs needed to enqueue
- *        (used for freeing other datagrams if not enough space)
- */
-static void
-ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed)
-{
-  struct ip6_reassdata *r, *oldest;
-
-  /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
-   * but don't free the current datagram! */
-  do {
-    r = oldest = reassdatagrams;
-    while (r != NULL) {
-      if (r != ipr) {
-        if (r->timer <= oldest->timer) {
-          /* older than the previous oldest */
-          oldest = r;
-        }
-      }
-      r = r->next;
-    }
-    if (oldest == ipr) {
-      /* nothing to free, ipr is the only element on the list */
-      return;
-    }
-    if (oldest != NULL) {
-      ip6_reass_free_complete_datagram(oldest);
-    }
-  } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL));
-}
-#endif /* IP_REASS_FREE_OLDEST */
-
-/**
- * Reassembles incoming IPv6 fragments into an IPv6 datagram.
- *
- * @param p points to the IPv6 Fragment Header
- * @return NULL if reassembly is incomplete, pbuf pointing to
- *         IPv6 Header if reassembly is complete
- */
-struct pbuf *
-ip6_reass(struct pbuf *p)
-{
-  struct ip6_reassdata *ipr, *ipr_prev;
-  struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
-  struct ip6_frag_hdr *frag_hdr;
-  u16_t offset, len;
-  u16_t clen;
-  u8_t valid = 1;
-  struct pbuf *q;
-
-  IP6_FRAG_STATS_INC(ip6_frag.recv);
-
-  if ((const void*)ip6_current_header() != ((u8_t*)p->payload) - IP6_HLEN) {
-    /* ip6_frag_hdr must be in the first pbuf, not chained */
-    IP6_FRAG_STATS_INC(ip6_frag.proterr);
-    IP6_FRAG_STATS_INC(ip6_frag.drop);
-    goto nullreturn;
-  }
-
-  frag_hdr = (struct ip6_frag_hdr *) p->payload;
-
-  clen = pbuf_clen(p);
-
-  offset = lwip_ntohs(frag_hdr->_fragment_offset);
-
-  /* Calculate fragment length from IPv6 payload length.
-   * Adjust for headers before Fragment Header.
-   * And finally adjust by Fragment Header length. */
-  len = lwip_ntohs(ip6_current_header()->_plen);
-  len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN);
-  len -= IP6_FRAG_HLEN;
-
-  /* Look for the datagram the fragment belongs to in the current datagram queue,
-   * remembering the previous in the queue for later dequeueing. */
-  for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) {
-    /* Check if the incoming fragment matches the one currently present
-       in the reassembly buffer. If so, we proceed with copying the
-       fragment into the buffer. */
-    if ((frag_hdr->_identification == ipr->identification) &&
-        ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) &&
-        ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) {
-      IP6_FRAG_STATS_INC(ip6_frag.cachehit);
-      break;
-    }
-    ipr_prev = ipr;
-  }
-
-  if (ipr == NULL) {
-  /* Enqueue a new datagram into the datagram queue */
-    ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
-    if (ipr == NULL) {
-#if IP_REASS_FREE_OLDEST
-      /* Make room and try again. */
-      ip6_reass_remove_oldest_datagram(ipr, clen);
-      ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
-      if (ipr != NULL) {
-        /* re-search ipr_prev since it might have been removed */
-        for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
-          if (ipr_prev->next == ipr) {
-            break;
-          }
-        }
-      } else
-#endif /* IP_REASS_FREE_OLDEST */
-      {
-        IP6_FRAG_STATS_INC(ip6_frag.memerr);
-        IP6_FRAG_STATS_INC(ip6_frag.drop);
-        goto nullreturn;
-      }
-    }
-
-    memset(ipr, 0, sizeof(struct ip6_reassdata));
-    ipr->timer = IP_REASS_MAXAGE;
-
-    /* enqueue the new structure to the front of the list */
-    ipr->next = reassdatagrams;
-    reassdatagrams = ipr;
-
-    /* Use the current IPv6 header for src/dest address reference.
-     * Eventually, we will replace it when we get the first fragment
-     * (it might be this one, in any case, it is done later). */
-#if IPV6_FRAG_COPYHEADER
-    MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
-#else /* IPV6_FRAG_COPYHEADER */
-    /* need to use the none-const pointer here: */
-    ipr->iphdr = ip_data.current_ip6_header;
-#endif /* IPV6_FRAG_COPYHEADER */
-
-    /* copy the fragmented packet id. */
-    ipr->identification = frag_hdr->_identification;
-
-    /* copy the nexth field */
-    ipr->nexth = frag_hdr->_nexth;
-  }
-
-  /* Check if we are allowed to enqueue more datagrams. */
-  if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
-#if IP_REASS_FREE_OLDEST
-    ip6_reass_remove_oldest_datagram(ipr, clen);
-    if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) {
-      /* re-search ipr_prev since it might have been removed */
-      for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
-        if (ipr_prev->next == ipr) {
-          break;
-        }
-      }
-    } else
-#endif /* IP_REASS_FREE_OLDEST */
-    {
-      /* @todo: send ICMPv6 time exceeded here? */
-      /* drop this pbuf */
-      IP6_FRAG_STATS_INC(ip6_frag.memerr);
-      IP6_FRAG_STATS_INC(ip6_frag.drop);
-      goto nullreturn;
-    }
-  }
-
-  /* Overwrite Fragment Header with our own helper struct. */
-#if IPV6_FRAG_COPYHEADER
-  if (IPV6_FRAG_REQROOM > 0) {
-    /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4).
-       This cannot fail since we already checked when receiving this fragment. */
-    u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
-    LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
-  }
-#else /* IPV6_FRAG_COPYHEADER */
-  LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
-    sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN);
-#endif /* IPV6_FRAG_COPYHEADER */
-  iprh = (struct ip6_reass_helper *)p->payload;
-  iprh->next_pbuf = NULL;
-  iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
-  iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
-
-  /* find the right place to insert this pbuf */
-  /* Iterate through until we either get to the end of the list (append),
-   * or we find on with a larger offset (insert). */
-  for (q = ipr->p; q != NULL;) {
-    iprh_tmp = (struct ip6_reass_helper*)q->payload;
-    if (iprh->start < iprh_tmp->start) {
-#if IP_REASS_CHECK_OVERLAP
-      if (iprh->end > iprh_tmp->start) {
-        /* fragment overlaps with following, throw away */
-        IP6_FRAG_STATS_INC(ip6_frag.proterr);
-        IP6_FRAG_STATS_INC(ip6_frag.drop);
-        goto nullreturn;
-      }
-      if (iprh_prev != NULL) {
-        if (iprh->start < iprh_prev->end) {
-          /* fragment overlaps with previous, throw away */
-          IP6_FRAG_STATS_INC(ip6_frag.proterr);
-          IP6_FRAG_STATS_INC(ip6_frag.drop);
-          goto nullreturn;
-        }
-      }
-#endif /* IP_REASS_CHECK_OVERLAP */
-      /* the new pbuf should be inserted before this */
-      iprh->next_pbuf = q;
-      if (iprh_prev != NULL) {
-        /* not the fragment with the lowest offset */
-        iprh_prev->next_pbuf = p;
-      } else {
-        /* fragment with the lowest offset */
-        ipr->p = p;
-      }
-      break;
-    } else if (iprh->start == iprh_tmp->start) {
-      /* received the same datagram twice: no need to keep the datagram */
-      IP6_FRAG_STATS_INC(ip6_frag.drop);
-      goto nullreturn;
-#if IP_REASS_CHECK_OVERLAP
-    } else if (iprh->start < iprh_tmp->end) {
-      /* overlap: no need to keep the new datagram */
-      IP6_FRAG_STATS_INC(ip6_frag.proterr);
-      IP6_FRAG_STATS_INC(ip6_frag.drop);
-      goto nullreturn;
-#endif /* IP_REASS_CHECK_OVERLAP */
-    } else {
-      /* Check if the fragments received so far have no gaps. */
-      if (iprh_prev != NULL) {
-        if (iprh_prev->end != iprh_tmp->start) {
-          /* There is a fragment missing between the current
-           * and the previous fragment */
-          valid = 0;
-        }
-      }
-    }
-    q = iprh_tmp->next_pbuf;
-    iprh_prev = iprh_tmp;
-  }
-
-  /* If q is NULL, then we made it to the end of the list. Determine what to do now */
-  if (q == NULL) {
-    if (iprh_prev != NULL) {
-      /* this is (for now), the fragment with the highest offset:
-       * chain it to the last fragment */
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      iprh_prev->next_pbuf = p;
-      if (iprh_prev->end != iprh->start) {
-        valid = 0;
-      }
-    } else {
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("no previous fragment, this must be the first fragment!",
-        ipr->p == NULL);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      /* this is the first fragment we ever received for this ip datagram */
-      ipr->p = p;
-    }
-  }
-
-  /* Track the current number of pbufs current 'in-flight', in order to limit
-  the number of fragments that may be enqueued at any one time */
-  ip6_reass_pbufcount += clen;
-
-  /* Remember IPv6 header if this is the first fragment. */
-  if (iprh->start == 0) {
-#if IPV6_FRAG_COPYHEADER
-    if (iprh->next_pbuf != NULL) {
-      MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
-    }
-#else /* IPV6_FRAG_COPYHEADER */
-    /* need to use the none-const pointer here: */
-    ipr->iphdr = ip_data.current_ip6_header;
-#endif /* IPV6_FRAG_COPYHEADER */
-  }
-
-  /* If this is the last fragment, calculate total packet length. */
-  if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
-    ipr->datagram_len = iprh->end;
-  }
-
-  /* Additional validity tests: we have received first and last fragment. */
-  iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload;
-  if (iprh_tmp->start != 0) {
-    valid = 0;
-  }
-  if (ipr->datagram_len == 0) {
-    valid = 0;
-  }
-
-  /* Final validity test: no gaps between current and last fragment. */
-  iprh_prev = iprh;
-  q = iprh->next_pbuf;
-  while ((q != NULL) && valid) {
-    iprh = (struct ip6_reass_helper*)q->payload;
-    if (iprh_prev->end != iprh->start) {
-      valid = 0;
-      break;
-    }
-    iprh_prev = iprh;
-    q = iprh->next_pbuf;
-  }
-
-  if (valid) {
-    /* All fragments have been received */
-    struct ip6_hdr* iphdr_ptr;
-
-    /* chain together the pbufs contained within the ip6_reassdata list. */
-    iprh = (struct ip6_reass_helper*) ipr->p->payload;
-    while (iprh != NULL) {
-      struct pbuf* next_pbuf = iprh->next_pbuf;
-      if (next_pbuf != NULL) {
-        /* Save next helper struct (will be hidden in next step). */
-        iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload;
-
-        /* hide the fragment header for every succeeding fragment */
-        pbuf_header(next_pbuf, -IP6_FRAG_HLEN);
-#if IPV6_FRAG_COPYHEADER
-        if (IPV6_FRAG_REQROOM > 0) {
-          /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */
-          u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
-          LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
-        }
-#endif
-        pbuf_cat(ipr->p, next_pbuf);
-      }
-      else {
-        iprh_tmp = NULL;
-      }
-
-      iprh = iprh_tmp;
-    }
-
-#if IPV6_FRAG_COPYHEADER
-    if (IPV6_FRAG_REQROOM > 0) {
-      /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */
-      u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
-      LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
-    }
-    iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
-    MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN);
-#else
-    iphdr_ptr = ipr->iphdr;
-#endif
-
-    /* Adjust datagram length by adding header lengths. */
-    ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr)
-                         + IP6_FRAG_HLEN
-                         - IP6_HLEN);
-
-    /* Set payload length in ip header. */
-    iphdr_ptr->_plen = lwip_htons(ipr->datagram_len);
-
-    /* Get the first pbuf. */
-    p = ipr->p;
-
-    /* Restore Fragment Header in first pbuf. Mark as "single fragment"
-     * packet. Restore nexth. */
-    frag_hdr = (struct ip6_frag_hdr *) p->payload;
-    frag_hdr->_nexth = ipr->nexth;
-    frag_hdr->reserved = 0;
-    frag_hdr->_fragment_offset = 0;
-    frag_hdr->_identification = 0;
-
-    /* release the sources allocate for the fragment queue entry */
-    if (reassdatagrams == ipr) {
-      /* it was the first in the list */
-      reassdatagrams = ipr->next;
-    } else {
-      /* it wasn't the first, so it must have a valid 'prev' */
-      LWIP_ASSERT("sanity check linked list", ipr_prev != NULL);
-      ipr_prev->next = ipr->next;
-    }
-    memp_free(MEMP_IP6_REASSDATA, ipr);
-
-    /* adjust the number of pbufs currently queued for reassembly. */
-    ip6_reass_pbufcount -= pbuf_clen(p);
-
-    /* Move pbuf back to IPv6 header.
-       This cannot fail since we already checked when receiving this fragment. */
-    if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) {
-      LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0);
-      pbuf_free(p);
-      return NULL;
-    }
-
-    /* Return the pbuf chain */
-    return p;
-  }
-  /* the datagram is not (yet?) reassembled completely */
-  return NULL;
-
-nullreturn:
-  pbuf_free(p);
-  return NULL;
-}
-
-#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
-
-#if LWIP_IPV6 && LWIP_IPV6_FRAG
-
-/** Allocate a new struct pbuf_custom_ref */
-static struct pbuf_custom_ref*
-ip6_frag_alloc_pbuf_custom_ref(void)
-{
-  return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
-}
-
-/** Free a struct pbuf_custom_ref */
-static void
-ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
-{
-  LWIP_ASSERT("p != NULL", p != NULL);
-  memp_free(MEMP_FRAG_PBUF, p);
-}
-
-/** Free-callback function to free a 'struct pbuf_custom_ref', called by
- * pbuf_free. */
-static void
-ip6_frag_free_pbuf_custom(struct pbuf *p)
-{
-  struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
-  LWIP_ASSERT("pcr != NULL", pcr != NULL);
-  LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
-  if (pcr->original != NULL) {
-    pbuf_free(pcr->original);
-  }
-  ip6_frag_free_pbuf_custom_ref(pcr);
-}
-
-/**
- * Fragment an IPv6 datagram if too large for the netif or path MTU.
- *
- * Chop the datagram in MTU sized chunks and send them in order
- * by pointing PBUF_REFs into p
- *
- * @param p ipv6 packet to send
- * @param netif the netif on which to send
- * @param dest destination ipv6 address to which to send
- *
- * @return ERR_OK if sent successfully, err_t otherwise
- */
-err_t
-ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
-{
-  struct ip6_hdr *original_ip6hdr;
-  struct ip6_hdr *ip6hdr;
-  struct ip6_frag_hdr *frag_hdr;
-  struct pbuf *rambuf;
-  struct pbuf *newpbuf;
-  static u32_t identification;
-  u16_t nfb;
-  u16_t left, cop;
-  u16_t mtu;
-  u16_t fragment_offset = 0;
-  u16_t last;
-  u16_t poff = IP6_HLEN;
-  u16_t newpbuflen = 0;
-  u16_t left_to_copy;
-
-  identification++;
-
-  original_ip6hdr = (struct ip6_hdr *)p->payload;
-
-  mtu = nd6_get_destination_mtu(dest, netif);
-
-  /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */
-  left = p->tot_len - IP6_HLEN;
-
-  nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;
-
-  while (left) {
-    last = (left <= nfb);
-
-    /* Fill this fragment */
-    cop = last ? left : nfb;
-
-    /* When not using a static buffer, create a chain of pbufs.
-     * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header.
-     * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
-     * but limited to the size of an mtu.
-     */
-    rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM);
-    if (rambuf == NULL) {
-      IP6_FRAG_STATS_INC(ip6_frag.memerr);
-      return ERR_MEM;
-    }
-    LWIP_ASSERT("this needs a pbuf in one piece!",
-                (p->len >= (IP6_HLEN)));
-    SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
-    ip6hdr = (struct ip6_hdr *)rambuf->payload;
-    frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);
-
-    /* Can just adjust p directly for needed offset. */
-    p->payload = (u8_t *)p->payload + poff;
-    p->len -= poff;
-    p->tot_len -= poff;
-
-    left_to_copy = cop;
-    while (left_to_copy) {
-      struct pbuf_custom_ref *pcr;
-      newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
-      /* Is this pbuf already empty? */
-      if (!newpbuflen) {
-        p = p->next;
-        continue;
-      }
-      pcr = ip6_frag_alloc_pbuf_custom_ref();
-      if (pcr == NULL) {
-        pbuf_free(rambuf);
-        IP6_FRAG_STATS_INC(ip6_frag.memerr);
-        return ERR_MEM;
-      }
-      /* Mirror this pbuf, although we might not need all of it. */
-      newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
-      if (newpbuf == NULL) {
-        ip6_frag_free_pbuf_custom_ref(pcr);
-        pbuf_free(rambuf);
-        IP6_FRAG_STATS_INC(ip6_frag.memerr);
-        return ERR_MEM;
-      }
-      pbuf_ref(p);
-      pcr->original = p;
-      pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;
-
-      /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
-       * so that it is removed when pbuf_dechain is later called on rambuf.
-       */
-      pbuf_cat(rambuf, newpbuf);
-      left_to_copy -= newpbuflen;
-      if (left_to_copy) {
-        p = p->next;
-      }
-    }
-    poff = newpbuflen;
-
-    /* Set headers */
-    frag_hdr->_nexth = original_ip6hdr->_nexth;
-    frag_hdr->reserved = 0;
-    frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
-    frag_hdr->_identification = lwip_htonl(identification);
-
-    IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
-    IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
-
-    /* No need for separate header pbuf - we allowed room for it in rambuf
-     * when allocated.
-     */
-    IP6_FRAG_STATS_INC(ip6_frag.xmit);
-    netif->output_ip6(netif, rambuf, dest);
-
-    /* Unfortunately we can't reuse rambuf - the hardware may still be
-     * using the buffer. Instead we free it (and the ensuing chain) and
-     * recreate it next time round the loop. If we're lucky the hardware
-     * will have already sent the packet, the free will really free, and
-     * there will be zero memory penalty.
-     */
-
-    pbuf_free(rambuf);
-    left -= cop;
-    fragment_offset += cop;
-  }
-  return ERR_OK;
-}
-
-#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff