From e41401fde93ac3ece5dd2ea07ab4c0897a550a9a Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 3 Mar 2026 16:30:46 +0100 Subject: [PATCH] chore: update to v2.2.0_20250106 modified by ST Signed-off-by: Frederic Pillon --- CHANGELOG | 233 ++++++++--- COPYING | 54 +-- FEATURES | 2 +- FILES | 19 +- LICENSE.md | 27 ++ README | 35 +- README.md | 2 +- UPGRADING | 11 + library.properties | 2 +- src/api/api_lib.c | 4 +- src/api/api_msg.c | 25 +- src/api/if_api.c | 2 +- src/api/netbuf.c | 4 +- src/api/netdb.c | 16 +- src/api/sockets.c | 368 +++++++++------- src/api/tcpip.c | 73 +++- src/arch/sys_arch.h | 2 +- src/compat/posix/net/if.h | 22 +- src/core/altcp.c | 10 +- src/core/altcp_alloc.c | 2 +- src/core/altcp_tcp.c | 5 +- src/core/def.c | 46 ++ src/core/dns.c | 62 ++- src/core/inet_chksum.c | 4 +- src/core/init.c | 19 +- src/core/ipv4/acd.c | 557 +++++++++++++++++++++++++ src/core/ipv4/autoip.c | 380 +++++------------ src/core/ipv4/dhcp.c | 300 ++++++------- src/core/ipv4/etharp.c | 87 ++-- src/core/ipv4/icmp.c | 30 +- src/core/ipv4/igmp.c | 24 +- src/core/ipv4/ip4.c | 50 ++- src/core/ipv4/ip4_addr.c | 2 +- src/core/ipv4/ip4_frag.c | 4 +- src/core/ipv6/dhcp6.c | 20 +- src/core/ipv6/icmp6.c | 13 +- src/core/ipv6/ip6.c | 31 +- src/core/ipv6/ip6_addr.c | 12 + src/core/ipv6/ip6_frag.c | 24 +- src/core/ipv6/mld6.c | 10 +- src/core/ipv6/nd6.c | 130 +++--- src/core/mem.c | 39 +- src/core/netif.c | 76 +++- src/core/pbuf.c | 54 +-- src/core/raw.c | 12 +- src/core/stats.c | 1 - src/core/sys.c | 12 +- src/core/tcp.c | 72 ++-- src/core/tcp_in.c | 67 +-- src/core/tcp_out.c | 175 +++++--- src/core/timeouts.c | 12 +- src/core/udp.c | 37 +- src/lwip/acd.h | 109 +++++ src/lwip/altcp.h | 5 +- src/lwip/altcp_tcp.h | 2 +- src/lwip/altcp_tls.h | 57 ++- src/lwip/api.h | 27 +- src/lwip/apps/altcp_tls_mbedtls_opts.h | 6 + src/lwip/apps/fs.h | 47 ++- src/lwip/apps/http_client.h | 14 +- src/lwip/apps/httpd.h | 1 + src/lwip/apps/httpd_opts.h | 26 +- src/lwip/apps/lwiperf.h | 11 +- src/lwip/apps/mdns.h | 59 ++- src/lwip/apps/mdns_domain.h | 80 ++++ src/lwip/apps/mdns_opts.h | 42 +- src/lwip/apps/mdns_out.h | 138 ++++++ src/lwip/apps/mdns_priv.h | 191 ++++++++- src/lwip/apps/mqtt.h | 8 +- src/lwip/apps/netbiosns_opts.h | 2 +- src/lwip/apps/smtp_opts.h | 7 +- src/lwip/apps/snmp.h | 14 +- src/lwip/apps/snmp_core.h | 2 +- src/lwip/apps/snmp_mib2.h | 2 +- src/lwip/apps/snmp_threadsync.h | 2 +- src/lwip/apps/sntp.h | 1 + src/lwip/apps/sntp_opts.h | 4 +- src/lwip/apps/tftp_client.h | 50 +++ src/lwip/apps/tftp_common.h | 108 +++++ src/lwip/apps/tftp_opts.h | 4 +- src/lwip/apps/tftp_server.h | 63 +-- src/lwip/arch.h | 59 +-- src/lwip/autoip.h | 23 +- src/lwip/debug.h | 10 +- src/lwip/def.h | 14 + src/lwip/dhcp.h | 48 ++- src/lwip/etharp.h | 5 + src/lwip/igmp.h | 2 +- src/lwip/inet.h | 19 + src/lwip/inet_chksum.h | 1 - src/lwip/init.h | 4 +- src/lwip/ip.h | 13 +- src/lwip/ip4.h | 2 - src/lwip/ip4_addr.h | 13 +- src/lwip/ip6_addr.h | 40 +- src/lwip/ip6_zone.h | 6 +- src/lwip/ip_addr.h | 76 +++- src/lwip/mem.h | 2 +- src/lwip/mld6.h | 2 +- src/lwip/netif.h | 51 ++- src/lwip/opt.h | 165 ++++++-- src/lwip/pbuf.h | 2 +- src/lwip/priv/altcp_priv.h | 2 +- src/lwip/priv/nd6_priv.h | 1 + src/lwip/priv/sockets_priv.h | 2 +- src/lwip/priv/tcp_priv.h | 16 +- src/lwip/priv/tcpip_priv.h | 8 +- src/lwip/prot/acd.h | 91 ++++ src/lwip/prot/autoip.h | 19 +- src/lwip/prot/ethernet.h | 4 +- src/lwip/prot/icmp.h | 30 +- src/lwip/prot/ieee.h | 2 +- src/lwip/prot/nd6.h | 1 + src/lwip/raw.h | 2 +- src/lwip/sio.h | 2 +- src/lwip/snmp.h | 2 +- src/lwip/sockets.h | 23 +- src/lwip/stats.h | 5 +- src/lwip/sys.h | 41 +- src/lwip/tcp.h | 8 +- src/lwip/tcpbase.h | 2 +- src/lwip/tcpip.h | 1 + src/lwip/udp.h | 2 +- src/netif/bridgeif.c | 4 +- src/netif/bridgeif_fdb.c | 6 +- src/netif/ethernet.c | 28 +- src/netif/lowpan6.c | 9 +- src/netif/lowpan6_ble.c | 38 +- src/netif/lowpan6_ble.h | 10 +- src/netif/lowpan6_common.c | 10 +- src/netif/lowpan6_opts.h | 2 +- src/netif/ppp/auth.c | 91 ++-- src/netif/ppp/ccp.c | 48 +-- src/netif/ppp/chap-new.c | 34 +- src/netif/ppp/chap_ms.c | 16 +- src/netif/ppp/demand.c | 10 +- src/netif/ppp/eap.c | 202 +++++---- src/netif/ppp/eap.h | 2 +- src/netif/ppp/fsm.c | 23 +- src/netif/ppp/ipcp.c | 44 +- src/netif/ppp/ipv6cp.c | 22 +- src/netif/ppp/lcp.c | 68 +-- src/netif/ppp/magic.c | 64 ++- src/netif/ppp/magic.h | 2 +- src/netif/ppp/multilink.c | 10 +- src/netif/ppp/ppp.c | 62 +-- src/netif/ppp/ppp.h | 2 +- src/netif/ppp/ppp_impl.h | 82 ++-- src/netif/ppp/ppp_opts.h | 45 +- src/netif/ppp/pppoe.c | 37 +- src/netif/ppp/pppoe.h | 2 +- src/netif/ppp/pppol2tp.c | 28 +- src/netif/ppp/pppos.c | 161 ++++--- src/netif/ppp/pppos.h | 7 +- src/netif/ppp/upap.c | 18 +- src/netif/ppp/utils.c | 36 +- src/netif/ppp/vj.c | 18 +- src/netif/ppp/vj.h | 4 +- src/netif/slipif.c | 12 +- src/netif/slipif.h | 1 - src/system/OS/sys_arch.c | 104 ++++- st_readme.txt | 66 ++- 162 files changed, 4532 insertions(+), 2079 deletions(-) create mode 100644 LICENSE.md create mode 100644 src/core/ipv4/acd.c create mode 100644 src/lwip/acd.h create mode 100644 src/lwip/apps/mdns_domain.h create mode 100644 src/lwip/apps/mdns_out.h create mode 100644 src/lwip/apps/tftp_client.h create mode 100644 src/lwip/apps/tftp_common.h create mode 100644 src/lwip/prot/acd.h diff --git a/CHANGELOG b/CHANGELOG index 5f797e7..90a5834 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,145 @@ HISTORY * [Enter new changes just after this line - do not remove this line] +(STABLE-2.2.1): + + ++ New features: + + 2023-10-11: Faidon Liambotis + * Add MEM_CUSTOM_ALLOCATOR and make LIBC a subset of it + + 2023-09-29: Jiri Findejs + * mqtt: support binary Will Message + + ++ Bugfixes: + + 2024-02-19: Simon Goldschmidt + * tcpip: fix that TCPIP_CORE_LOCK is not released for LWIP_TIMERS==0 + + 2024-01-09: Simon Goldschmidt + * snmp v3, ppp: prevent possible timing attacks by using a constant-runtime-memcmp when + checking credentials + + 2023-01-04: Simon Goldschmidt + * makefsdata: update tinydir.h to newest version (1.2.6) + + 2023-10-12: Borys Szefler + * dhcp: fix memory corruption when LWIP_DHCP_MAX_DNS_SERVERS > DNS_MAX_SERVERS + + 2023-10-11: Mazakazu + * sockets: fix socket leak when using setsockopt/getsockopt hook with LWIP_NETCONN_FULLDUPLEX==1 + + 2023-10-10: Simon Goldschmidt + * sockets: fix bug #63898: allow socket option IPV6_CHECKSUM for both IPPROTO_IPV6 and IPPROTO_RAW + + 2023-10-10: Simon Goldschmidt + * ipv6: fix ip6_current_header() after reassembly + + 2023-10-07: Simon Goldschmidt + * ipv6 reassembly: fix detecting holes in reassembled packets + + 2023-10-04: Simon Goldschmidt + * apps: http client: improve the HTTP client; ensure connection settings are passed + + 2023-10-03: Simon Goldschmidt + * ipv6: frag: fix bogus icmp6 response on reassembly timeout + + 2023-09-28: Szabolcs Szekelyi + * httpd: ensure headers are parsed case-insensitive + + 2023-09-28: Erik Ekman + * Fix ND6 Router Advertisement parsing when NETIF_MAX_HWADDR_LEN is above 6. + + 2023-09-27: Hardy Griech + * Fix iperf byte counting mode + +(STABLE-2.2.0): + + 2018-10-02: Dirk Ziegelmeier + * Integrate contrib repository into main lwIP repository + + ++ New features: + + 2022-04-05: David Cermak + * contrib/addons: Add example of using DHCP extra options hooks + + 2023-05-11: David Cermak + * dhcp: Add macro for appending extra client's request options + + 2023-05-11: xueyunfei + * dhcp: Enable custom config for timeouts, thresholds, backoff time + + 2021-04-26 + * test/unit: added more unit tests + + 2020-03-27: Simon Goldschmidt + * test/fuzz: improve fuzz test + + 2019-12-11: Simon Goldschmidt + * ip6addr_aton: support scoped address strings (via '%') + + 2019-08-28: Joan Lledó + * Contrib: Add kFreeBSD to the Unix port + + 2019-07-14: Joan Lledó + * Unix port: improve support for the Hurd + + ++ Bugfixes: + + 2019-12-11: David Girault + * altcp_tls: support for saving/restoring session information + + 2018-11-16: Craig McQUeen + * dns: allow a DNS look-up with a trailing dot in the name + + 2018-10-19: Timmy Brolin + * Add outgoing VLAN PCP support for Ethernet level QoS + + 2018-10-08: Ben Wijen + * apps/tftp: added TFTP client + + 2018-10-04: Jasper Verschueren + * Implement IPv4 ACD (Address Conflict Detection) + + 2023-05-10 + * altcp_tls_mbedtls: note which version of mbedtls we are compatible to + * altcp_tls_mbedtls: multiple compatibility fixes + + 2023-04-26: Jan Breuer, Harrold Spier, Ognjen Bjelica, Dirk Ziegelmeier, Simon Goldschmidt + * apps/snmp: multiple fixes and improvements to snmp + + 2022-01-12: Simon Goldschmidt + * httpd: clean up custom file handling + + 2021-11-25: quanjia + * ping: fix sockaddr len in ping_send() for PING_USE_SOCKETS==1 + + 2021-11-12: Bas Prins + * http_client: reset timeout when receiving data + + 2020-07-07: Erik Ekman + * Rename IP and Ethernet equality checkers from _cmp to _eq + + 2020-03-05: Simon Goldschmidt + * tcp: tighten up checks for received SYN + + 2020-01-30: Simon Goldschmidt, David Girault, David J. Fiddes, Tom Ferrin + * apps/sntp: multiple fixes and improvements for sntp + + 2020-01-30: Simon Goldschmidt + * ip_forward: fix IPv4 forwarding with multiple netifs/offloading + + 2019-06-11: David Girault, Giuseppe Modugno + * apps/mqtt: multiple fixes for mqtt + + 2019-05-19: Joan Lledó + * New function tcpip_callback_wait() + Call a function inside the tcpip thread and block the calling thread until + the callback finishes + + 2018-08-15: Jasper Verschueren, David Girault, Our Air Quality + * apps/mdns: greatly improved the mdns client + (STABLE-2.1.2): ++ Bugfixes: @@ -177,7 +316,7 @@ HISTORY 2017-01-20: Joel Cunningham * sockets: add interface name/index APIs (task #14314) - + 2017-01-08: David van Moolenbroek * Extensions to RAW API (patch #9208) - Connected RAW PCBs @@ -266,7 +405,7 @@ HISTORY 2017-08-02: Abroz Bizjak/Simon Goldschmidt * multiple fixes in IPv4 reassembly (leading to corrupted datagrams received) - + 2017-03-30: Simon Goldschmidt * dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf @@ -411,7 +550,7 @@ HISTORY 2016-11-14: Joel Cunningham * tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit - in window) + in window) 2016-11-16: Roberto Barbieri Carrera * autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address) @@ -686,7 +825,7 @@ HISTORY 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. + - 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. @@ -1218,7 +1357,7 @@ HISTORY 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 @@ -1300,10 +1439,10 @@ HISTORY 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 @@ -1758,7 +1897,7 @@ HISTORY 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 @@ -1811,7 +1950,7 @@ HISTORY 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. @@ -1856,21 +1995,21 @@ HISTORY 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 + * 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 @@ -1974,7 +2113,7 @@ HISTORY 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. + 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 @@ -2434,7 +2573,7 @@ HISTORY sent to mbox 2009-06-25 Kieran Mansley - * api_msg.c api.h: BUG26722: initialise netconn write variables + * api_msg.c api.h: BUG26722: initialise netconn write variables in netconn_alloc 2009-06-25 Kieran Mansley @@ -2442,7 +2581,7 @@ HISTORY 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 + simultaneous close behaviour, and make snd_nxt have the same meaning as in the RFCs. 2009-05-12 Simon Goldschmidt @@ -2578,7 +2717,7 @@ HISTORY * 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 + * 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) @@ -2614,7 +2753,7 @@ HISTORY out of pool pbufs. 2008-12-19 Simon Goldschmidt - * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + * 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 @@ -2699,7 +2838,7 @@ HISTORY 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.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 @@ -2709,7 +2848,7 @@ HISTORY 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 @@ -2735,8 +2874,8 @@ HISTORY 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 + 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. @@ -2860,7 +2999,7 @@ HISTORY 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 + * 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. @@ -2880,7 +3019,7 @@ HISTORY 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 + * 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). @@ -2904,7 +3043,7 @@ HISTORY 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 + 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 @@ -2985,7 +3124,7 @@ HISTORY 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). + 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". @@ -2997,11 +3136,11 @@ HISTORY 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 + 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 + * 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. @@ -3208,32 +3347,32 @@ HISTORY 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 + * 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 + 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 + 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). + * 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 + 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). @@ -3256,7 +3395,7 @@ HISTORY * 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: + * 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) @@ -3298,7 +3437,7 @@ HISTORY 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) + 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. @@ -3415,7 +3554,7 @@ HISTORY 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 + lwip_getsockname use now a common lwip_getaddrname function since netconn_peer & netconn_addr have the same parameters). 2007-09-20 Simon Goldschmidt @@ -3435,13 +3574,13 @@ HISTORY 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, + * 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 + 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 @@ -3539,7 +3678,7 @@ HISTORY 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...) + 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. @@ -3641,7 +3780,7 @@ HISTORY 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 + 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). @@ -3788,7 +3927,7 @@ HISTORY 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 + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with network interfaces. Also fix a compiler warning. 2007-03-20 Kieran Mansley @@ -3880,13 +4019,13 @@ HISTORY * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call interval. - 2007-02-28 Kieran Mansley + 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 + 2007-02-28 Kieran Mansley * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero - when supplied timeout is also non-zero + when supplied timeout is also non-zero (STABLE-1.2.0) @@ -3970,7 +4109,7 @@ HISTORY in accept() by Kevin Lawson. 2006-05-26 Christiaan Simons - * api_lib.c: Removed conn->sem creation and destruction + * api_lib.c: Removed conn->sem creation and destruction from netconn_write() and added sys_sem_new to netconn_new_*. (STABLE-1_1_1) @@ -4040,7 +4179,7 @@ HISTORY * 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_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.) diff --git a/COPYING b/COPYING index e23898b..90465f5 100644 --- a/COPYING +++ b/COPYING @@ -1,33 +1,25 @@ -/* - * 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 - * - */ +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. diff --git a/FEATURES b/FEATURES index a50c5a5..87802d1 100644 --- a/FEATURES +++ b/FEATURES @@ -4,7 +4,7 @@ The focus of the lwIP TCP/IP implementation is to reduce resource usage while st Main features include: - Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE, 6LowPAN (via IEEE 802.15.4, BLE or ZEP; since v2.1.0) -- DHCP client, stateless DHCPv6 (since v2.1.0), DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3 (since v2.1.0), private MIB support & MIB compiler) +- DHCP client, stateless DHCPv6 (since v2.1.0), DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), ACD (Address Conflict Detection), SNMP agent (v1, v2c, v3 (since v2.1.0), private MIB support & MIB compiler) - APIs: specialized APIs for enhanced performance & zero copy, optional Berkeley-alike socket API - Extended features: IP forwarding over multiple network interfaces - Extended TCP features: congestion control, RTT estimation and fast recovery/fast retransmit, sending SACKs (since v2.1.0), "altcp": nearly transparent TLS for any tcp pcb (since v2.1.0) diff --git a/FILES b/FILES index 0be0741..2a7086c 100644 --- a/FILES +++ b/FILES @@ -1,15 +1,6 @@ -api/ - The code for the high-level wrapper API. Not needed if - you use the lowel-level call-back/raw API. +contrib/ - lwIP examples, ports, and small apps (formerly http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git/) +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. -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. +See also the FILES file in each subdirectory. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c0c9afc --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,27 @@ +# Portions COPYRIGHT 2016 STMicroelectronics +# 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. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. \ No newline at end of file diff --git a/README b/README index b95f155..f831051 100644 --- a/README +++ b/README @@ -17,12 +17,13 @@ FEATURES 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 + * 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) - * DHCP, AutoIP/APIPA (Zeroconf) and (stateless) DHCPv6 + * DHCP, AutoIP/APIPA (Zeroconf), ACD (Address Conflict Detection) + and (stateless) DHCPv6 * UDP (User Datagram Protocol) including experimental UDP-lite extensions * TCP (Transmission Control Protocol) with congestion control, RTT estimation fast recovery/fast retransmit and sending SACKs @@ -63,37 +64,39 @@ 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. +The lwIP TCP/IP stack is maintained in the 'src' directory and +contributions (such as platform ports and applications) are in +the 'contrib' directory. 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 +The current Git tree is web-browsable: + https://git.savannah.gnu.org/cgit/lwip.git Submit patches and bugs via the lwIP project page: - http://savannah.nongnu.org/projects/lwip/ + https://savannah.nongnu.org/projects/lwip/ Continuous integration builds (GCC, clang): - https://travis-ci.org/yarrick/lwip-merged + https://github.com/lwip-tcpip/lwip/actions 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 + https://www.nongnu.org/lwip/ Also, there are mailing lists you can subscribe at - http://savannah.nongnu.org/mail/?group=lwip + https://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/ + https://lists.nongnu.org/archive/html/lwip-users/ + https://lists.nongnu.org/archive/html/lwip-devel/ + +There is a wiki about lwIP at + https://lwip.wikia.com/wiki/LwIP_Wiki +You might get questions answered there, but unfortunately, it is not as +well maintained as it should be. lwIP was originally written by Adam Dunkels: http://dunkels.com/adam/ diff --git a/README.md b/README.md index ef4916c..c1d769e 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ ## Version -This library is based on the LwIP stack modified by ST: [stm32_mw_lwip](https://github.com/STMicroelectronics/stm32_mw_lwip) version [v2.1.3_230818](https://github.com/STMicroelectronics/stm32_mw_lwip/releases/tag/v2.1.3_230818). +This library is based on the LwIP stack modified by ST: [stm32_mw_lwip](https://github.com/STMicroelectronics/stm32_mw_lwip) version [v2.2.0_20250106](https://github.com/STMicroelectronics/stm32_mw_lwip/releases/tag/v2.2.0_20250106). diff --git a/UPGRADING b/UPGRADING index 21ad8cc..ac77cf5 100644 --- a/UPGRADING +++ b/UPGRADING @@ -7,6 +7,17 @@ with newer versions. (git master) * [Enter new changes just after this line - do not remove this line] + * The eth_addr_cmp and ip_addr_cmp set of functions have been renamed to eth_addr_eq, ip_addr_eq + and so on, since they return non-zero on equality. Macros for the old names exist. + * The sio_write function used by PPP now takes the data argument as const. + * The prev field in the snmp_varbind struct has been removed. + +(2.2.0) + + ++ Repository changes: + + * The contrib repository has been added into the main repository in the subdirectory 'contrib' + (the old contrib repository remains online for reference but is not used any more) (2.1.0) diff --git a/library.properties b/library.properties index 5a3518a..6a5902c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino LwIP -version=2.1.3 +version=2.2.0 author=Adam Dunkels maintainer=See url sentence=A Lightweight TCP/IP stack diff --git a/src/api/api_lib.c b/src/api/api_lib.c index ffa14d6..60678f8 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -323,7 +323,7 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind */ if ((netconn_get_ipv6only(conn) == 0) && - ip_addr_cmp(addr, IP6_ADDR_ANY)) { + ip_addr_eq(addr, IP6_ADDR_ANY)) { addr = IP_ANY_TYPE; } #endif /* LWIP_IPV4 && LWIP_IPV6 */ @@ -1260,13 +1260,13 @@ netconn_join_leave_group_netif(struct netconn *conn, * * @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 +/** @param dns_addrtype IP address type (IPv4 / IPv6) */ err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) #else diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 3f08e03..8092be9 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -93,7 +93,7 @@ static void netconn_drain(struct netconn *conn); #endif /* LWIP_TCPIP_CORE_LOCKING */ #if LWIP_NETCONN_FULLDUPLEX -const u8_t netconn_deleted = 0; +static const u8_t netconn_deleted = 0; int lwip_netconn_is_deallocated_msg(void *msg) @@ -106,9 +106,9 @@ lwip_netconn_is_deallocated_msg(void *msg) #endif /* LWIP_NETCONN_FULLDUPLEX */ #if LWIP_TCP -const u8_t netconn_aborted = 0; -const u8_t netconn_reset = 0; -const u8_t netconn_closed = 0; +static const u8_t netconn_aborted = 0; +static const u8_t netconn_reset = 0; +static const u8_t netconn_closed = 0; /** Translate an error to a unique void* passed via an mbox */ static void * @@ -221,6 +221,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct netbuf *buf; struct netconn *conn; u16_t len; + err_t err; #if LWIP_SO_RCVBUF int recv_avail; #endif /* LWIP_SO_RCVBUF */ @@ -269,8 +270,10 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, } len = p->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + err = sys_mbox_trypost(&conn->recvmbox, buf); + if (err != ERR_OK) { netbuf_delete(buf); + LWIP_DEBUGF(API_MSG_DEBUG, ("recv_udp: sys_mbox_trypost failed, err=%d\n", err)); return; } else { #if LWIP_SO_RCVBUF @@ -469,7 +472,7 @@ err_tcp(void *arg, err_t err) } /* pass error message to acceptmbox to wake up pending accept */ if (NETCONN_MBOX_VALID(conn, &conn->acceptmbox)) { - /* use trypost to preven deadlock */ + /* use trypost to prevent deadlock */ sys_mbox_trypost(&conn->acceptmbox, mbox_msg); } @@ -492,7 +495,7 @@ err_tcp(void *arg, err_t err) 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)); + LWIP_ASSERT("invalid op_completed_sem", sys_sem_valid(op_completed_sem)); conn->current_msg = NULL; /* wake up the waiting task */ sys_sem_signal(op_completed_sem); @@ -759,10 +762,8 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) 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_arg.socket = -1; conn->callback = callback; #if LWIP_TCP conn->current_msg = NULL; @@ -978,7 +979,7 @@ lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) /* Try to close the connection */ if (shut_close) { #if LWIP_SO_LINGER - /* check linger possibilites before calling tcp_close */ + /* check linger possibilities 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)) { @@ -1472,7 +1473,7 @@ lwip_netconn_do_listen(void *m) /* "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) && + if (ip_addr_eq(&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); diff --git a/src/api/if_api.c b/src/api/if_api.c index 8e094d0..d274c32 100644 --- a/src/api/if_api.c +++ b/src/api/if_api.c @@ -77,7 +77,7 @@ lwip_if_indextoname(unsigned int ifindex, char *ifname) /** * @ingroup if_api - * Returs the interface index corresponding to name ifname. + * Returns the interface index corresponding to name ifname. * @param ifname Interface name * @return The corresponding index if ifname is the name of an interface; * otherwise, zero. diff --git a/src/api/netbuf.c b/src/api/netbuf.c index 3b910de..8f5be9e 100644 --- a/src/api/netbuf.c +++ b/src/api/netbuf.c @@ -5,8 +5,8 @@ * @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 + * to avoid copying data around.
+ * Buffers must not be shared across multiple threads, all functions except * netbuf_new() and netbuf_delete() are not thread-safe. */ diff --git a/src/api/netdb.c b/src/api/netdb.c index ee78297..73028c8 100644 --- a/src/api/netdb.c +++ b/src/api/netdb.c @@ -40,6 +40,7 @@ #if LWIP_DNS && LWIP_SOCKET #include "lwip/err.h" +#include "lwip/errno.h" #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/ip_addr.h" @@ -61,13 +62,18 @@ struct gethostbyname_r_helper { 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 */ +/** LWIP_DNS_API_HOSTENT_STORAGE: if set to 0 (default), lwip_gethostbyname() + * returns the same global variable for all calls (in all threads). + * When set to 1, 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. + */ #ifndef LWIP_DNS_API_HOSTENT_STORAGE #define LWIP_DNS_API_HOSTENT_STORAGE 0 #endif -/** define "hostent" variables storage */ +/* define "hostent" variables storage */ #if LWIP_DNS_API_HOSTENT_STORAGE #define HOSTENT_STORAGE #else @@ -377,7 +383,9 @@ lwip_getaddrinfo(const char *nodename, const char *servname, /* set up sockaddr */ inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; +#if LWIP_SOCKET_HAVE_SA_LEN sa6->sin6_len = sizeof(struct sockaddr_in6); +#endif /* LWIP_SOCKET_HAVE_SA_LEN */ sa6->sin6_port = lwip_htons((u16_t)port_nr); sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); ai->ai_family = AF_INET6; @@ -388,7 +396,9 @@ lwip_getaddrinfo(const char *nodename, const char *servname, /* set up sockaddr */ inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; +#if LWIP_SOCKET_HAVE_SA_LEN sa4->sin_len = sizeof(struct sockaddr_in); +#endif /* LWIP_SOCKET_HAVE_SA_LEN */ sa4->sin_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET; #endif /* LWIP_IPV4 */ diff --git a/src/api/sockets.c b/src/api/sockets.c index 7852635..b97bdd7 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -85,9 +85,53 @@ #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) +#ifndef LWIP_SOCKET_HAVE_SA_LEN +#define LWIP_SOCKET_HAVE_SA_LEN 0 +#endif /* LWIP_SOCKET_HAVE_SA_LEN */ + +/* Address length safe read and write */ +#if LWIP_SOCKET_HAVE_SA_LEN + +#if LWIP_IPV4 +#define IP4ADDR_SOCKADDR_SET_LEN(sin) \ + (sin)->sin_len = sizeof(struct sockaddr_in) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_SOCKADDR_SET_LEN(sin6) \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6) +#endif /* LWIP_IPV6 */ + +#define IPADDR_SOCKADDR_GET_LEN(addr) \ + (addr)->sa.sa_len + +#else + +#if LWIP_IPV4 +#define IP4ADDR_SOCKADDR_SET_LEN(addr) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_SOCKADDR_SET_LEN(addr) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +#define IPADDR_SOCKADDR_GET_LEN(addr) \ + ((addr)->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) \ + : ((addr)->sa.sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : 0)) +#elif LWIP_IPV4 +#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr_in) +#elif LWIP_IPV6 +#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr_in6) +#else +#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#endif /* LWIP_SOCKET_HAVE_SA_LEN */ + #if LWIP_IPV4 #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ - (sin)->sin_len = sizeof(struct sockaddr_in); \ + IP4ADDR_SOCKADDR_SET_LEN(sin); \ (sin)->sin_family = AF_INET; \ (sin)->sin_port = lwip_htons((port)); \ inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ @@ -99,7 +143,7 @@ #if LWIP_IPV6 #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ - (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + IP6ADDR_SOCKADDR_SET_LEN(sin6); \ (sin6)->sin6_family = AF_INET6; \ (sin6)->sin6_port = lwip_htons((port)); \ (sin6)->sin6_flowinfo = 0; \ @@ -156,7 +200,7 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t * 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 IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % LWIP_MIN(4, MEM_ALIGNMENT)) == 0) #define LWIP_SOCKOPT_CHECK_OPTLEN(sock, optlen, opttype) do { if ((optlen) < sizeof(opttype)) { done_socket(sock); return EINVAL; }}while(0) @@ -178,7 +222,7 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t * #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); \ + set_errno(ENOMEM); \ done_socket(sock); \ return -1; \ } }while(0) @@ -278,11 +322,6 @@ static volatile int select_cb_ctr; static struct lwip_select_cb *select_cb_list; #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */ -#define sock_set_errno(sk, e) do { \ - const int sockerr = (e); \ - set_errno(sockerr); \ -} while (0) - /* Forward declaration of some functions */ #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); @@ -621,7 +660,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) { struct lwip_sock *sock, *nsock; struct netconn *newconn; - ip_addr_t naddr; + ip_addr_t naddr = {0}; u16_t port = 0; int newsock; err_t err; @@ -639,11 +678,11 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) 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); + set_errno(EOPNOTSUPP); } else if (err == ERR_CLSD) { - sock_set_errno(sock, EINVAL); + set_errno(EINVAL); } else { - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); } done_socket(sock); return -1; @@ -653,32 +692,13 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) newsock = alloc_socket(newconn, 1); if (newsock == -1) { netconn_delete(newconn); - sock_set_errno(sock, ENFILE); + set_errno(ENFILE); done_socket(sock); return -1; } LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); 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); - recvevent = (s16_t)(-1 - newconn->socket); - newconn->socket = newsock; - SYS_ARCH_UNPROTECT(lev); - - if (newconn->callback) { - LOCK_TCPIP_CORE(); - while (recvevent > 0) { - recvevent--; - newconn->callback(newconn, NETCONN_EVT_RCVPLUS, 0); - } - UNLOCK_TCPIP_CORE(); - } - /* Note that POSIX only requires us to check addr is non-NULL. addrlen must * not be NULL if addr is valid. */ @@ -689,25 +709,46 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); free_socket(nsock, 1); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); - if (*addrlen > tempaddr.sa.sa_len) { - *addrlen = tempaddr.sa.sa_len; + if (*addrlen > IPADDR_SOCKADDR_GET_LEN(&tempaddr)) { + *addrlen = IPADDR_SOCKADDR_GET_LEN(&tempaddr); } MEMCPY(addr, &tempaddr, *addrlen); + } + + /* 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); + recvevent = (s16_t)(-1 - newconn->callback_arg.socket); + newconn->callback_arg.socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + if (newconn->callback) { + LOCK_TCPIP_CORE(); + while (recvevent > 0) { + recvevent--; + newconn->callback(newconn, NETCONN_EVT_RCVPLUS, 0); + } + UNLOCK_TCPIP_CORE(); + } + if ((addr != NULL) && (addrlen != NULL)) { 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)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d\n", s, newsock)); } - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); done_socket(nsock); return newsock; @@ -728,7 +769,7 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); + set_errno(err_to_errno(ERR_VAL)); done_socket(sock); return -1; } @@ -736,7 +777,7 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) /* 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)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); LWIP_UNUSED_ARG(namelen); SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); @@ -756,13 +797,13 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) 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)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; } @@ -798,7 +839,7 @@ lwip_close(int s) err = netconn_prepare_delete(sock->conn); if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } @@ -821,7 +862,7 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) 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)); + set_errno(err_to_errno(ERR_VAL)); done_socket(sock); return -1; } @@ -837,7 +878,7 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) /* 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)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); @@ -857,13 +898,13 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) 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)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; } @@ -897,15 +938,15 @@ lwip_listen(int s, int 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); + set_errno(EOPNOTSUPP); } else { - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); } done_socket(sock); return -1; } - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; } @@ -954,7 +995,7 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags) /* We should really do some error checking here. */ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: p == NULL, error is \"%s\"!\n", lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); if (err == ERR_CLSD) { return 0; } else { @@ -973,7 +1014,7 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags) } else { copylen = (u16_t)recv_left; } - if (recvd + copylen < recvd) { + if (recvd > SSIZE_MAX - copylen) { /* overflow */ copylen = (u16_t)(SSIZE_MAX - recvd); } @@ -1012,7 +1053,7 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags) /* ensure window update after copying all data */ netconn_tcp_recvd(sock->conn, (size_t)recvd); } - sock_set_errno(sock, 0); + set_errno(0); return recvd; } #endif @@ -1040,10 +1081,10 @@ lwip_sock_make_addr(struct netconn *conn, ip_addr_t *fromaddr, u16_t port, #endif /* LWIP_IPV4 && LWIP_IPV6 */ IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); - if (*fromlen < saddr.sa.sa_len) { + if (*fromlen < IPADDR_SOCKADDR_GET_LEN(&saddr)) { truncated = 1; - } else if (*fromlen > saddr.sa.sa_len) { - *fromlen = saddr.sa.sa_len; + } else if (*fromlen > IPADDR_SOCKADDR_GET_LEN(&saddr)) { + *fromlen = IPADDR_SOCKADDR_GET_LEN(&saddr); } MEMCPY(from, &saddr, *fromlen); return truncated; @@ -1090,7 +1131,7 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16 u8_t apiflags; err_t err; u16_t buflen, copylen, copied; - int i; + msg_iovlen_t i; LWIP_UNUSED_ARG(dbg_s); LWIP_ERROR("lwip_recvfrom_udp_raw: invalid arguments", (msg->msg_iov != NULL) || (msg->msg_iovlen <= 0), return ERR_ARG;); @@ -1232,7 +1273,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags, if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n", s, lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } @@ -1242,7 +1283,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags, } } - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return ret; } @@ -1280,7 +1321,7 @@ ssize_t lwip_recvmsg(int s, struct msghdr *message, int flags) { struct lwip_sock *sock; - int i; + msg_iovlen_t i; ssize_t buflen; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, (void *)message, flags)); @@ -1304,7 +1345,7 @@ lwip_recvmsg(int s, struct msghdr *message, int flags) if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) || ((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) || ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) { - sock_set_errno(sock, err_to_errno(ERR_VAL)); + set_errno(err_to_errno(ERR_VAL)); done_socket(sock); return -1; } @@ -1338,13 +1379,13 @@ lwip_recvmsg(int s, struct msghdr *message, int flags) } if (buflen > 0) { /* reset socket error since we have received something */ - sock_set_errno(sock, 0); + set_errno(0); } /* " If the socket is connected, the msg_name and msg_namelen members shall be ignored." */ done_socket(sock); return buflen; #else /* LWIP_TCP */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* LWIP_TCP */ @@ -1358,7 +1399,7 @@ lwip_recvmsg(int s, struct msghdr *message, int flags) if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n", s, lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } @@ -1366,12 +1407,12 @@ lwip_recvmsg(int s, struct msghdr *message, int flags) message->msg_flags |= MSG_TRUNC; } - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return (int)datagram_len; } #else /* LWIP_UDP || LWIP_RAW */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* LWIP_UDP || LWIP_RAW */ @@ -1398,7 +1439,7 @@ lwip_send(int s, const void *data, size_t size, int flags) done_socket(sock); return lwip_sendto(s, data, size, flags, NULL, 0); #else /* (LWIP_UDP || LWIP_RAW) */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* (LWIP_UDP || LWIP_RAW) */ @@ -1411,7 +1452,7 @@ lwip_send(int s, const void *data, size_t size, int flags) 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)); + set_errno(err_to_errno(err)); done_socket(sock); /* casting 'written' to ssize_t is OK here since the netconn API limits it to SSIZE_MAX */ return (err == ERR_OK ? (ssize_t)written : -1); @@ -1433,13 +1474,13 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags) } LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", msg->msg_iov != NULL, - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); LWIP_ERROR("lwip_sendmsg: maximum iovs exceeded", (msg->msg_iovlen > 0) && (msg->msg_iovlen <= IOV_MAX), - sock_set_errno(sock, EMSGSIZE); done_socket(sock); return -1;); + set_errno(EMSGSIZE); done_socket(sock); return -1;); LWIP_ERROR("lwip_sendmsg: unsupported flags", (flags & ~(MSG_DONTWAIT | MSG_MORE)) == 0, - sock_set_errno(sock, EOPNOTSUPP); done_socket(sock); return -1;); + set_errno(EOPNOTSUPP); done_socket(sock); return -1;); LWIP_UNUSED_ARG(msg->msg_control); LWIP_UNUSED_ARG(msg->msg_controllen); @@ -1453,12 +1494,12 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags) written = 0; err = netconn_write_vectors_partly(sock->conn, (struct netvector *)msg->msg_iov, (u16_t)msg->msg_iovlen, write_flags, &written); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); /* casting 'written' to ssize_t is OK here since the netconn API limits it to SSIZE_MAX */ return (err == ERR_OK ? (ssize_t)written : -1); #else /* LWIP_TCP */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* LWIP_TCP */ @@ -1467,13 +1508,13 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags) #if LWIP_UDP || LWIP_RAW { struct netbuf chain_buf; - int i; + msg_iovlen_t i; ssize_t size = 0; 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)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); /* initialize chain buffer with destination */ memset(&chain_buf, 0, sizeof(struct netbuf)); @@ -1564,17 +1605,17 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags) /* deallocated the buffer */ netbuf_free(&chain_buf); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return (err == ERR_OK ? size : -1); sendmsg_emsgsize: - sock_set_errno(sock, EMSGSIZE); + set_errno(EMSGSIZE); netbuf_free(&chain_buf); done_socket(sock); return -1; } #else /* LWIP_UDP || LWIP_RAW */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* LWIP_UDP || LWIP_RAW */ @@ -1601,7 +1642,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, return lwip_send(s, data, size, flags); #else /* LWIP_TCP */ LWIP_UNUSED_ARG(flags); - sock_set_errno(sock, err_to_errno(ERR_ARG)); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1; #endif /* LWIP_TCP */ @@ -1609,7 +1650,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { /* cannot fit into one datagram (at least for us) */ - sock_set_errno(sock, EMSGSIZE); + set_errno(EMSGSIZE); done_socket(sock); return -1; } @@ -1617,7 +1658,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || (IS_SOCK_ADDR_LEN_VALID(tolen) && ((to != NULL) && (IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))))), - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); + set_errno(err_to_errno(ERR_ARG)); done_socket(sock); return -1;); LWIP_UNUSED_ARG(tolen); /* initialize a buffer */ @@ -1675,7 +1716,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, /* deallocated the buffer */ netbuf_free(&buf); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return (err == ERR_OK ? short_size : -1); } @@ -1734,7 +1775,7 @@ lwip_socket(int domain, int type, int protocol) set_errno(ENFILE); return -1; } - conn->socket = i; + conn->callback_arg.socket = i; done_socket(&sockets[i - LWIP_SOCKET_OFFSET]); LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); set_errno(0); @@ -2076,7 +2117,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, set_errno(EBADF); } else if (!nready) { /* Still none ready, just wait to be woken */ - if (timeout == 0) { + if (timeout == NULL) { /* Wait forever */ msectimeout = 0; } else { @@ -2490,7 +2531,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) /* Get socket */ if (conn) { - s = conn->socket; + s = conn->callback_arg.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. @@ -2498,16 +2539,16 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) * 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 (conn->callback_arg.socket < 0) { if (evt == NETCONN_EVT_RCVPLUS) { /* conn->socket is -1 on initialization lwip_accept adjusts sock->recvevent if conn->socket < -1 */ - conn->socket--; + conn->callback_arg.socket--; } SYS_ARCH_UNPROTECT(lev); return; } - s = conn->socket; + s = conn->callback_arg.socket; SYS_ARCH_UNPROTECT(lev); } @@ -2673,12 +2714,12 @@ lwip_shutdown(int s, int how) if (sock->conn != NULL) { if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); + set_errno(EOPNOTSUPP); done_socket(sock); return -1; } } else { - sock_set_errno(sock, ENOTCONN); + set_errno(ENOTCONN); done_socket(sock); return -1; } @@ -2691,13 +2732,13 @@ lwip_shutdown(int s, int how) shut_rx = 1; shut_tx = 1; } else { - sock_set_errno(sock, EINVAL); + set_errno(EINVAL); done_socket(sock); return -1; } err = netconn_shutdown(sock->conn, shut_rx, shut_tx); - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return (err == ERR_OK ? 0 : -1); } @@ -2719,7 +2760,7 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) /* get the IP address and port */ err = netconn_getaddr(sock->conn, &naddr, &port, local); if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); + set_errno(err_to_errno(err)); done_socket(sock); return -1; } @@ -2739,12 +2780,12 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) 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; + if (*namelen > IPADDR_SOCKADDR_GET_LEN(&saddr)) { + *namelen = IPADDR_SOCKADDR_GET_LEN(&saddr); } MEMCPY(name, &saddr, *namelen); - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; } @@ -2776,7 +2817,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) } if ((NULL == optval) || (NULL == optlen)) { - sock_set_errno(sock, EFAULT); + set_errno(EFAULT); done_socket(sock); return -1; } @@ -2792,7 +2833,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) #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); + set_errno(ENOBUFS); done_socket(sock); return -1; } @@ -2815,7 +2856,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) cberr = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); if (cberr != ERR_OK) { LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(cberr)); + set_errno(err_to_errno(cberr)); done_socket(sock); return -1; } @@ -2828,12 +2869,12 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); #endif /* LWIP_MPU_COMPATIBLE */ - /* maybe lwip_getsockopt_internal has changed err */ + /* maybe lwip_getsockopt_impl 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); + set_errno(err); done_socket(sock); return err ? -1 : 0; } @@ -2881,6 +2922,49 @@ lwip_sockopt_to_ipopt(int optname) } } +#if LWIP_IPV6 && LWIP_RAW +static void +lwip_getsockopt_impl_ipv6_checksum(int s, struct lwip_sock* sock, void* optval) +{ + 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))); +} + +static int +lwip_setsockopt_impl_ipv6_checksum(int s, struct lwip_sock* sock, const void* optval, socklen_t optlen) +{ + /* It should not be possible to disable the checksum generation with ICMPv6 + * as per RFC 3542 chapter 3.1 */ + if (sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { + done_socket(sock); + return EINVAL; + } + + 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 */ + done_socket(sock); + 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)); + return 0; +} +#endif + /** lwip_getsockopt_impl: the actual implementation of getsockopt: * same argument as lwip_getsockopt, either called directly or through callback */ @@ -2895,6 +2979,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt #ifdef LWIP_HOOK_SOCKETS_GETSOCKOPT if (LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, &err)) { + done_socket(sock); return err; } #endif @@ -3130,6 +3215,12 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt /* Level: IPPROTO_IPV6 */ case IPPROTO_IPV6: switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + lwip_getsockopt_impl_ipv6_checksum(s, sock, optval); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ case IPV6_V6ONLY: LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); *(int *)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); @@ -3180,13 +3271,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt #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)) ); + lwip_getsockopt_impl_ipv6_checksum(s, sock, optval); break; #endif /* LWIP_IPV6 && LWIP_RAW */ default: @@ -3222,7 +3307,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt } if (NULL == optval) { - sock_set_errno(sock, EFAULT); + set_errno(EFAULT); done_socket(sock); return -1; } @@ -3238,7 +3323,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt #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); + set_errno(ENOBUFS); done_socket(sock); return -1; } @@ -3263,18 +3348,18 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt cberr = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); if (cberr != ERR_OK) { LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(cberr)); + set_errno(err_to_errno(cberr)); done_socket(sock); 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 */ + /* maybe lwip_setsockopt_impl 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); + set_errno(err); done_socket(sock); return err ? -1 : 0; } @@ -3316,6 +3401,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_ #ifdef LWIP_HOOK_SOCKETS_SETSOCKOPT if (LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, &err)) { + done_socket(sock); return err; } #endif @@ -3607,7 +3693,15 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_ /* Level: IPPROTO_IPV6 */ case IPPROTO_IPV6: switch (optname) { - case IPV6_V6ONLY: +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + err = lwip_setsockopt_impl_ipv6_checksum(s, sock, optval, optlen); + if (err) { + return err; + } + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + case IPV6_V6ONLY: LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); if (*(const int *)optval) { netconn_set_ipv6only(sock->conn, 1); @@ -3705,26 +3799,10 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_ switch (optname) { #if LWIP_IPV6 && LWIP_RAW case IPV6_CHECKSUM: - /* It should not be possible to disable the checksum generation with ICMPv6 - * as per RFC 3542 chapter 3.1 */ - if (sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { - done_socket(sock); - return EINVAL; - } - - 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 */ - done_socket(sock); - return EINVAL; - } else { - sock->conn->pcb.raw->chksum_reqd = 1; - sock->conn->pcb.raw->chksum_offset = (u16_t) * (const int *)optval; + err = lwip_setsockopt_impl_ipv6_checksum(s, sock, optval, optlen); + if (err) { + return err; } - 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: @@ -3762,7 +3840,7 @@ lwip_ioctl(int s, long cmd, void *argp) #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE case FIONREAD: if (!argp) { - sock_set_errno(sock, EINVAL); + set_errno(EINVAL); done_socket(sock); return -1; } @@ -3805,7 +3883,7 @@ lwip_ioctl(int s, long cmd, void *argp) *((int *)argp) = recv_avail; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; #else /* LWIP_SO_RCVBUF */ @@ -3820,7 +3898,7 @@ lwip_ioctl(int s, long cmd, void *argp) } netconn_set_nonblocking(sock->conn, val); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); - sock_set_errno(sock, 0); + set_errno(0); done_socket(sock); return 0; @@ -3828,7 +3906,7 @@ lwip_ioctl(int s, long cmd, void *argp) 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 */ + set_errno(ENOSYS); /* not yet implemented */ done_socket(sock); return -1; } @@ -3852,7 +3930,7 @@ lwip_fcntl(int s, int cmd, int val) switch (cmd) { case F_GETFL: ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; - sock_set_errno(sock, 0); + set_errno(0); if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { #if LWIP_TCPIP_CORE_LOCKING @@ -3893,14 +3971,14 @@ lwip_fcntl(int s, int cmd, int val) /* only O_NONBLOCK, all other bits are zero */ netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); ret = 0; - sock_set_errno(sock, 0); + set_errno(0); } else { - sock_set_errno(sock, ENOSYS); /* not yet implemented */ + set_errno(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 */ + set_errno(ENOSYS); /* not yet implemented */ break; } done_socket(sock); @@ -4031,8 +4109,8 @@ lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_ad 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)) { + ip4_addr_eq(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_eq(&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); @@ -4120,7 +4198,7 @@ lwip_socket_unregister_mld6_membership(int s, unsigned int if_idx, const ip6_add for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { if ((socket_ipv6_multicast_memberships[i].sock == sock) && (socket_ipv6_multicast_memberships[i].if_idx == if_idx) && - ip6_addr_cmp(&socket_ipv6_multicast_memberships[i].multi_addr, multi_addr)) { + ip6_addr_eq(&socket_ipv6_multicast_memberships[i].multi_addr, multi_addr)) { socket_ipv6_multicast_memberships[i].sock = NULL; socket_ipv6_multicast_memberships[i].if_idx = NETIF_NO_INDEX; ip6_addr_set_zero(&socket_ipv6_multicast_memberships[i].multi_addr); diff --git a/src/api/tcpip.c b/src/api/tcpip.c index a7e312a..0891f9e 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -68,11 +68,20 @@ sys_mutex_t lock_tcpip_core; static void tcpip_thread_handle_msg(struct tcpip_msg *msg); #if !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) + +/** Wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ +static void +tcpip_mbox_fetch(sys_mbox_t* mbox, void** msg) +{ + LWIP_ASSERT_CORE_LOCKED(); + + UNLOCK_TCPIP_CORE(); + sys_mbox_fetch(mbox, msg); + LOCK_TCPIP_CORE(); +} + #else /* !LWIP_TIMERS */ -/* wait for a message, timeouts are processed while waiting */ -#define TCPIP_MBOX_FETCH(mbox, msg) tcpip_timeouts_mbox_fetch(mbox, msg) + /** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts are processed. @@ -81,7 +90,7 @@ static void tcpip_thread_handle_msg(struct tcpip_msg *msg); * @param msg the place to store the message */ static void -tcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +tcpip_mbox_fetch(sys_mbox_t *mbox, void **msg) { u32_t sleeptime, res; @@ -139,7 +148,7 @@ tcpip_thread(void *arg) while (1) { /* MAIN Loop */ LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ - TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg); + tcpip_mbox_fetch(&tcpip_mbox, (void **)&msg); if (msg == NULL) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); LWIP_ASSERT("tcpip_thread: invalid message", 0); @@ -166,6 +175,11 @@ tcpip_thread_handle_msg(struct tcpip_msg *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; + case TCPIP_MSG_CALLBACK_STATIC_WAIT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK WAIT message %p\n", (void *)msg)); + msg->msg.cb_wait.function(msg->msg.cb_wait.ctx); + sys_sem_signal(msg->msg.cb_wait.sem); + break; #endif /* !LWIP_TCPIP_CORE_LOCKING */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT @@ -423,7 +437,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg) /** * 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, + * on a provided semaphore, which is 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. @@ -519,7 +533,7 @@ tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) * e.g. the message is allocated once and posted several times from an IRQ * using tcpip_callbackmsg_trycallback(). * Example usage: Trigger execution of an ethernet IRQ DPC routine in lwIP thread context. - * + * * @param function the function to call * @param ctx parameter passed to function * @return a struct pointer to pass to tcpip_callbackmsg_trycallback(). @@ -589,6 +603,49 @@ tcpip_callbackmsg_trycallback_fromisr(struct tcpip_callback_msg *msg) return sys_mbox_trypost_fromisr(&tcpip_mbox, msg); } +/** + * Sends a message to TCPIP thread to call a function. Caller thread blocks + * until the function returns. + * 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 function the function to call + * @param ctx parameter passed to f + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_wait(tcpip_callback_fn function, void *ctx) +{ +#if LWIP_TCPIP_CORE_LOCKING + LOCK_TCPIP_CORE(); + function(ctx); + UNLOCK_TCPIP_CORE(); + return ERR_OK; +#else /* LWIP_TCPIP_CORE_LOCKING */ + err_t err; + sys_sem_t sem; + struct tcpip_msg msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox)); + + err = sys_sem_new(&sem, 0); + if (err != ERR_OK) { + return err; + } + + msg.type = TCPIP_MSG_CALLBACK_STATIC_WAIT; + msg.msg.cb_wait.function = function; + msg.msg.cb_wait.ctx = ctx; + msg.msg.cb_wait.sem = &sem; + sys_mbox_post(&tcpip_mbox, &msg); + sys_arch_sem_wait(&sem, 0); + sys_sem_free(&sem); + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +} + /** * @ingroup lwip_os * Initialize this module: diff --git a/src/arch/sys_arch.h b/src/arch/sys_arch.h index d02cf6f..9fde554 100644 --- a/src/arch/sys_arch.h +++ b/src/arch/sys_arch.h @@ -48,7 +48,7 @@ extern "C" { #define SYS_SEM_NULL (osSemaphoreId_t)0 typedef osSemaphoreId_t sys_sem_t; -typedef osSemaphoreId_t sys_mutex_t; +typedef osMutexId_t sys_mutex_t; typedef osMessageQueueId_t sys_mbox_t; typedef osThreadId_t sys_thread_t; diff --git a/src/compat/posix/net/if.h b/src/compat/posix/net/if.h index 6b8e63a..8b8e481 100644 --- a/src/compat/posix/net/if.h +++ b/src/compat/posix/net/if.h @@ -7,7 +7,7 @@ * Copyright (c) 2017 Joel Cunningham, Garmin International, Inc. * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, @@ -16,17 +16,17 @@ * 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. + * 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 + * 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. diff --git a/src/core/altcp.c b/src/core/altcp.c index 4abef7c..9644e82 100644 --- a/src/core/altcp.c +++ b/src/core/altcp.c @@ -40,7 +40,7 @@ * * Replace "struct tcp_pcb" with "struct altcp_pcb" * * Prefix all called tcp API functions with "altcp_" instead of "tcp_" to link * against the altcp functions - * * @ref altcp_new (and @ref altcp_new_ip_type/@ref altcp_new_ip6) take + * * @ref altcp_new (and @ref altcp_new_ip_type / @ref altcp_new_ip6) take * an @ref altcp_allocator_t as an argument, whereas the original tcp API * functions take no arguments. * * An @ref altcp_allocator_t allocator is an object that holds a pointer to an @@ -75,7 +75,7 @@ * It is not defined by lwIP itself but by the TLS port (e.g. altcp_tls to mbedTLS * adaption). However, the parameters used to create it are defined in @ref * altcp_tls.h (see @ref altcp_tls_create_config_server_privkey_cert for servers - * and @ref altcp_tls_create_config_client/@ref altcp_tls_create_config_client_2wayauth + * and @ref altcp_tls_create_config_client / @ref altcp_tls_create_config_client_2wayauth * for clients). * * For mbedTLS, ensure that certificates can be parsed by 'mbedtls_x509_crt_parse()' and @@ -158,7 +158,7 @@ altcp_free(struct altcp_pcb *conn) /** * @ingroup altcp - * altcp_new_ip6: @ref altcp_new for IPv6 + * altcp_new_ip6: @ref altcp_new for IPv6 */ struct altcp_pcb * altcp_new_ip6(altcp_allocator_t *allocator) @@ -166,9 +166,9 @@ altcp_new_ip6(altcp_allocator_t *allocator) return altcp_new_ip_type(allocator, IPADDR_TYPE_V6); } -/** +/** * @ingroup altcp - * altcp_new: @ref altcp_new for IPv4 + * altcp_new: @ref altcp_new for IPv4 */ struct altcp_pcb * altcp_new(altcp_allocator_t *allocator) diff --git a/src/core/altcp_alloc.c b/src/core/altcp_alloc.c index cd619bc..06ed90d 100644 --- a/src/core/altcp_alloc.c +++ b/src/core/altcp_alloc.c @@ -1,6 +1,6 @@ /** * @file - * Application layered TCP connection API (to be used from TCPIP thread)\n + * Application layered TCP connection API (to be used from TCPIP thread)
* This interface mimics the tcp callback API to the application while preventing * direct linking (much like virtual functions). * This way, an application can make use of other application layer protocols diff --git a/src/core/altcp_tcp.c b/src/core/altcp_tcp.c index 1869e2a..4f21b70 100644 --- a/src/core/altcp_tcp.c +++ b/src/core/altcp_tcp.c @@ -1,6 +1,7 @@ /** * @file - * Application layered TCP connection API (to be used from TCPIP thread)\n + * Application layered TCP connection API (to be used from TCPIP thread) + * * This interface mimics the tcp callback API to the application while preventing * direct linking (much like virtual functions). * This way, an application can make use of other application layer protocols @@ -74,7 +75,7 @@ static err_t altcp_tcp_accept(void *arg, struct tcp_pcb *new_tpcb, err_t err) { struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg; - if (listen_conn && listen_conn->accept) { + if (new_tpcb && listen_conn && listen_conn->accept) { /* create a new altcp_conn to pass to the next 'accept' callback */ struct altcp_pcb *new_conn = altcp_alloc(); if (new_conn == NULL) { diff --git a/src/core/def.c b/src/core/def.c index 9da36fe..11ad31b 100644 --- a/src/core/def.c +++ b/src/core/def.c @@ -118,6 +118,29 @@ lwip_strnstr(const char *buffer, const char *token, size_t n) } #endif +#ifndef lwip_strnistr +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnistr() non-standard function. + * This can be \#defined to strnistr() depending on your platform port. + */ +char * +lwip_strnistr(const char *buffer, const char *token, size_t n) +{ + const char *p; + size_t tokenlen = strlen(token); + if (tokenlen == 0) { + return LWIP_CONST_CAST(char *, buffer); + } + for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { + if (lwip_strnicmp(p, token, tokenlen) == 0) { + return LWIP_CONST_CAST(char *, p); + } + } + return NULL; +} +#endif + #ifndef lwip_stricmp /** * @ingroup sys_nonstandard @@ -238,3 +261,26 @@ lwip_itoa(char *result, size_t bufsize, int number) memmove(res, tmp, (size_t)((result + bufsize) - tmp)); } #endif + +#ifndef lwip_memcmp_consttime +/** + * @ingroup sys_nonstandard + * The goal of this function is to compare memory with constant runtime in order to prevent + * timing attacks to various parts in the stack. + * To do that, in contrast to memcmp(), it only returns: + * 0: equal + * != 0: not equal + */ +int lwip_memcmp_consttime(const void* s1, const void* s2, size_t len) +{ + size_t i; + const unsigned char* a1 = (const unsigned char*)s1; + const unsigned char* a2 = (const unsigned char*)s2; + unsigned char ret = 0; + + for (i = 0; i < len; i++) { + ret |= a1[i] ^ a2[i]; + } + return ret; +} +#endif diff --git a/src/core/dns.c b/src/core/dns.c index 9d2f61e..6540f14 100644 --- a/src/core/dns.c +++ b/src/core/dns.c @@ -277,7 +277,7 @@ DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ static void dns_init_local(void); -static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); +static err_t dns_lookup_local(const char *hostname, size_t hostnamelen, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); #endif /* DNS_LOCAL_HOSTLIST */ @@ -476,18 +476,32 @@ dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg) err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype) { + size_t hostnamelen; LWIP_UNUSED_ARG(dns_addrtype); - return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); + if ((addr == NULL) || + (!hostname) || (!hostname[0])) { + return ERR_ARG; + } + hostnamelen = strlen(hostname); + if (hostname[hostnamelen - 1] == '.') { + hostnamelen--; + } + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_local_lookup: name too long to resolve\n")); + return ERR_ARG; + } + return dns_lookup_local(hostname, hostnamelen, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); } /* Internal implementation for dns_local_lookup and dns_lookup */ static err_t -dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +dns_lookup_local(const char *hostname, size_t hostnamelen, 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) && + if ((lwip_strnicmp(entry->name, hostname, hostnamelen) == 0) && + !entry->name[hostnamelen] && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { if (addr) { ip_addr_copy(*addr, entry->addr); @@ -499,7 +513,8 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_ #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ size_t i; for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && + if ((lwip_strnicmp(local_hostlist_static[i].name, hostname, hostnamelen) == 0) && + !local_hostlist_static[i].name[hostnamelen] && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { if (addr) { ip_addr_copy(*addr, local_hostlist_static[i].addr); @@ -530,7 +545,7 @@ dns_local_removehost(const char *hostname, const ip_addr_t *addr) 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))) { + ((addr == NULL) || ip_addr_eq(&entry->addr, addr))) { struct local_hostlist_entry *free_entry; if (last_entry != NULL) { last_entry->next = entry->next; @@ -593,30 +608,34 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr) * for a hostname. * * @param name the hostname to look up + * @param hostnamelen length of the hostname * @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)) +dns_lookup(const char *name, size_t hostnamelen, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) { + size_t namelen; u8_t i; #if DNS_LOCAL_HOSTLIST - if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + if (dns_lookup_local(name, hostnamelen, 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) { + if (DNS_LOOKUP_LOCAL_EXTERN(name, hostnamelen, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) { return ERR_OK; } #endif /* DNS_LOOKUP_LOCAL_EXTERN */ + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH - 1); /* 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_strnicmp(name, dns_table[i].name, namelen) == 0) && + !dns_table[i].name[namelen] && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); ip_addr_debug_print_val(DNS_DEBUG, dns_table[i].ipaddr); @@ -1218,7 +1237,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, { /* 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])) { + if (!ip_addr_eq(addr, &dns_servers[entry->server_idx])) { goto ignore_packet; /* ignore this packet */ } } @@ -1380,13 +1399,18 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, 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; +#endif + + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH - 1); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) /* 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)) { + (lwip_strnicmp(name, dns_table[i].name, namelen) == 0) && + !dns_table[i].name[namelen]) { #if LWIP_IPV4 && LWIP_IPV6 if (dns_table[i].reqaddrtype != dns_addrtype) { /* requested address types don't match @@ -1397,7 +1421,7 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, #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) { + if (dns_requests[r].found == NULL) { dns_requests[r].found = found; dns_requests[r].arg = callback_arg; dns_requests[r].dns_table_idx = i; @@ -1473,7 +1497,6 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, 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; @@ -1563,8 +1586,11 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call } #endif hostnamelen = strlen(hostname); + if (hostname[hostnamelen - 1] == '.') { + hostnamelen--; + } if (hostnamelen >= DNS_MAX_NAME_LENGTH) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); + LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve\n")); return ERR_ARG; } @@ -1587,7 +1613,7 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call } } /* already have this address cached? */ - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + if (dns_lookup(hostname, hostnamelen, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { return ERR_OK; } #if LWIP_IPV4 && LWIP_IPV6 @@ -1599,7 +1625,7 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call } else { fallback = LWIP_DNS_ADDRTYPE_IPV4; } - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { + if (dns_lookup(hostname, hostnamelen, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { return ERR_OK; } } diff --git a/src/core/inet_chksum.c b/src/core/inet_chksum.c index 818c68f..6a343ed 100644 --- a/src/core/inet_chksum.c +++ b/src/core/inet_chksum.c @@ -1,6 +1,6 @@ /** * @file - * Internet checksum functions.\n + * Internet checksum functions. * * These are some reference implementations of the checksum algorithm, with the * aim of being simple, correct and fully portable. Checksumming is the @@ -74,7 +74,7 @@ u16_t lwip_standard_chksum(const void *dataptr, int len); * @return host order (!) lwip checksum (non-inverted Internet sum) * * @note accumulator size limits summable length to 64k - * @note host endianess is irrelevant (p3 RFC1071) + * @note host endianness is irrelevant (p3 RFC1071) */ u16_t lwip_standard_chksum(const void *dataptr, int len) diff --git a/src/core/init.c b/src/core/init.c index 3620e1d..b906eff 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -127,7 +127,7 @@ PACK_STRUCT_END #endif /* There must be sufficient timeouts, taking into account requirements of the subsystems. */ #if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < LWIP_NUM_SYS_TIMEOUT_INTERNAL) -#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#error "MEMP_NUM_SYS_TIMEOUT is too low to accommodate 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!" @@ -184,8 +184,8 @@ PACK_STRUCT_END #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" +#if (((!LWIP_DHCP) || (!LWIP_ARP) || (!LWIP_ACD)) && LWIP_DHCP_DOES_ACD_CHECK) +#error "If you want to use DHCP ACD checking, you have to define LWIP_DHCP=1, LWIP_ARP=1 and LWIP_ACD=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" @@ -196,8 +196,11 @@ PACK_STRUCT_END #if (LWIP_ALTCP && LWIP_EVENT_API) #error "The application layered tcp API does not work with LWIP_EVENT_API" #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" +#if (MEM_CUSTOM_ALLOCATOR && !(defined(MEM_CUSTOM_FREE) && defined(MEM_CUSTOM_MALLOC) && defined(MEM_CUSTOM_CALLOC))) +#error "All of MEM_CUSTOM_FREE/MEM_CUSTOM_MALLOC/MEM_CUSTOM_CALLOC must be provided if MEM_CUSTOM_ALLOCATOR is enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && MEM_CUSTOM_ALLOCATOR) +#error "MEM_USE_POOLS may not be used with a custom allocator (MEM_CUSTOM_ALLOCATOR or MEM_LIBC_MALLOC) 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" @@ -220,6 +223,9 @@ PACK_STRUCT_END #if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" #endif +#if PPP_SUPPORT && CCP_SUPPORT && !MPPE_SUPPORT +#error "CCP_SUPPORT needs MPPE_SUPPORT 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 @@ -306,6 +312,9 @@ PACK_STRUCT_END #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_MSS >= ((16 * 1024) - 1) +#error "lwip_sanity_check: WARNING: TCP_MSS must be <= 16382 to prevent u16_t underflow in TCP_SNDLOWAT calculation!" +#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 diff --git a/src/core/ipv4/acd.c b/src/core/ipv4/acd.c new file mode 100644 index 0000000..92f3b5a --- /dev/null +++ b/src/core/ipv4/acd.c @@ -0,0 +1,557 @@ +/** + * @file + * + * ACD IPv4 Address Conflict Detection + * + * This is an IPv4 address conflict detection implementation for the lwIP TCP/IP + * stack. It aims to be conform to RFC5227. + * + * @defgroup acd ACD + * @ingroup ip4 + * ACD related functions + * USAGE: + * + * define @ref LWIP_ACD 1 in your lwipopts.h + * Options: + * ACD_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 .... + * + * For fixed IP: + * - call acd_start after selecting an IP address. The caller will be informed + * on conflict status via the callback function. + * + * With AUTOIP: + * - will be called from the autoip module. No extra's needed. + * + * With DHCP: + * - enable LWIP_DHCP_DOES_ACD_CHECK. Then it will be called from the dhcp module. + * No extra's needed. + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * Copyright (c) 2018 Jasper Verschueren + * 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: Jasper Verschueren + * Author: Dominik Spies + */ + +#include "lwip/opt.h" + +/* don't build if not configured for use in lwipopts.h */ +#if LWIP_IPV4 && LWIP_ACD + +#include + +#include "lwip/acd.h" +#include "lwip/prot/acd.h" + +#define ACD_FOREACH(acd, acd_list) for ((acd) = acd_list; (acd) != NULL; (acd) = (acd)->next) + +#define ACD_TICKS_PER_SECOND (1000 / ACD_TMR_INTERVAL) + +/* Define good random function (LWIP_RAND) in lwipopts.h */ +#ifdef LWIP_RAND +#define LWIP_ACD_RAND(netif, acd) LWIP_RAND() +#else /* LWIP_RAND */ +#ifdef LWIP_AUTOIP_RAND +#include "lwip/autoip.h" +#define LWIP_ACD_RAND(netif, acd) LWIP_AUTOIP_RAND(netif) /* for backwards compatibility */ +#else +#define LWIP_ACD_RAND(netif, acd) ((((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))) + \ + (acd->sent_num)) +#endif /* LWIP_AUTOIP_RAND */ +#endif /* LWIP_RAND */ + + +#define ACD_RANDOM_PROBE_WAIT(netif, acd) (LWIP_ACD_RAND(netif, acd) % \ + (PROBE_WAIT * ACD_TICKS_PER_SECOND)) + +#define ACD_RANDOM_PROBE_INTERVAL(netif, acd) ((LWIP_ACD_RAND(netif, acd) % \ + ((PROBE_MAX - PROBE_MIN) * ACD_TICKS_PER_SECOND)) + \ + (PROBE_MIN * ACD_TICKS_PER_SECOND )) + +/* Function definitions */ +static void acd_restart(struct netif *netif, struct acd *acd); +static void acd_handle_arp_conflict(struct netif *netif, struct acd *acd); +static void acd_put_in_passive_mode(struct netif *netif, struct acd *acd); + +/** + * @ingroup acd + * Add ACD client to the client list and initialize callback function + * + * @param netif network interface on which to start the acd + * client + * @param acd acd module to be added to the list + * @param acd_conflict_callback callback to be called when conflict information + * is available + */ +err_t +acd_add(struct netif *netif, struct acd *acd, + acd_conflict_callback_t acd_conflict_callback) +{ + struct acd *acd2; + + /* Set callback */ + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("acd_conflict_callback != NULL", acd_conflict_callback != NULL); + acd->acd_conflict_callback = acd_conflict_callback; + + /* Check if the acd struct is already added */ + for (acd2 = netif->acd_list; acd2 != NULL; acd2 = acd2->next) { + if (acd2 == acd) { + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_add(): acd already added to list\n")); + return ERR_OK; + } + } + + /* add acd struct to the list */ + acd->next = netif->acd_list; + netif->acd_list = acd; + + return ERR_OK; +} + +/** + * @ingroup acd + * Remove ACD client from the client list + * + * @param netif network interface from which to remove the acd client + * @param acd acd module to be removed from the list + */ +void +acd_remove(struct netif *netif, struct acd *acd) +{ + struct acd *acd2, *prev = NULL; + + LWIP_ASSERT_CORE_LOCKED(); + + for (acd2 = netif->acd_list; acd2 != NULL; acd2 = acd2->next) { + if (acd2 == acd) { + if (prev) { + prev->next = acd->next; + } else { + netif->acd_list = acd->next; + } + return; + } + prev = acd2; + } + LWIP_ASSERT(("acd_remove(): acd not on list\n"), 0); +} + + +/** + * @ingroup acd + * Start ACD client + * + * @param netif network interface on which to start the acd client + * @param acd acd module to start + * @param ipaddr ip address to perform acd on + */ +err_t +acd_start(struct netif *netif, struct acd *acd, ip4_addr_t ipaddr) +{ + err_t result = ERR_OK; + + LWIP_UNUSED_ARG(netif); + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_start(netif=%p) %c%c%"U16_F"\n", + (void *)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + + /* init probing state */ + acd->sent_num = 0; + acd->lastconflict = 0; + ip4_addr_copy(acd->ipaddr, ipaddr); + acd->state = ACD_STATE_PROBE_WAIT; + + acd->ttw = (u16_t)(ACD_RANDOM_PROBE_WAIT(netif, acd)); + + return result; +} + +/** + * @ingroup acd + * Stop ACD client + * + * @param acd acd module to stop + */ +err_t +acd_stop(struct acd *acd) +{ + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("acd_stop\n")); + + if (acd != NULL) { + acd->state = ACD_STATE_OFF; + } + return ERR_OK; +} + +/** + * @ingroup acd + * Inform the ACD modules when the link goes down + * + * @param netif network interface on which to inform the ACD clients + */ +void +acd_network_changed_link_down(struct netif *netif) +{ + struct acd *acd; + /* loop over the acd's*/ + ACD_FOREACH(acd, netif->acd_list) { + acd_stop(acd); + } +} + +/** + * Has to be called in loop every ACD_TMR_INTERVAL milliseconds + */ +void +acd_tmr(void) +{ + struct netif *netif; + struct acd *acd; + /* loop through netif's */ + NETIF_FOREACH(netif) { + ACD_FOREACH(acd, netif->acd_list) { + if (acd->lastconflict > 0) { + acd->lastconflict--; + } + + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE, + ("acd_tmr() ACD-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(acd->state), acd->ttw)); + + if (acd->ttw > 0) { + acd->ttw--; + } + + switch (acd->state) { + case ACD_STATE_PROBE_WAIT: + case ACD_STATE_PROBING: + if (acd->ttw == 0) { + acd->state = ACD_STATE_PROBING; + etharp_acd_probe(netif, &acd->ipaddr); + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE, + ("acd_tmr() PROBING Sent Probe\n")); + acd->sent_num++; + if (acd->sent_num >= PROBE_NUM) { + /* Switch to ANNOUNCE_WAIT: last probe is sent*/ + acd->state = ACD_STATE_ANNOUNCE_WAIT; + + acd->sent_num = 0; + + /* calculate time to wait before announcing */ + acd->ttw = (u16_t)(ANNOUNCE_WAIT * ACD_TICKS_PER_SECOND); + } else { + /* calculate time to wait to next probe */ + acd->ttw = (u16_t)(ACD_RANDOM_PROBE_INTERVAL(netif, acd)); + } + } + break; + + case ACD_STATE_ANNOUNCE_WAIT: + case ACD_STATE_ANNOUNCING: + if (acd->ttw == 0) { + if (acd->sent_num == 0) { + acd->state = ACD_STATE_ANNOUNCING; + + /* reset conflict count to ensure fast re-probing after announcing */ + acd->num_conflicts = 0; + + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr), + ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr))); + } + + etharp_acd_announce(netif, &acd->ipaddr); + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE, + ("acd_tmr() ANNOUNCING Sent Announce\n")); + acd->ttw = ANNOUNCE_INTERVAL * ACD_TICKS_PER_SECOND; + acd->sent_num++; + + if (acd->sent_num >= ANNOUNCE_NUM) { + acd->state = ACD_STATE_ONGOING; + acd->sent_num = 0; + acd->ttw = 0; + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_tmr(): changing state to ONGOING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr), + ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr))); + + /* finally, let acd user know that the address is good and can be used */ + acd->acd_conflict_callback(netif, ACD_IP_OK); + } + } + break; + + case ACD_STATE_RATE_LIMIT: + if (acd->ttw == 0) { + /* acd should be stopped because ipaddr isn't valid any more */ + acd_stop(acd); + /* let the acd user (after rate limit interval) know that their is + * a conflict detected. So it can restart the address acquiring + * process.*/ + acd->acd_conflict_callback(netif, ACD_RESTART_CLIENT); + } + break; + + default: + /* nothing to do in other states */ + break; + } + } + } +} + +/** + * Restarts the acd module + * + * The number of conflicts is increased and the upper layer is informed. + */ +static void +acd_restart(struct netif *netif, struct acd *acd) +{ + /* increase conflict counter. */ + acd->num_conflicts++; + + /* Decline the address */ + acd->acd_conflict_callback(netif, ACD_DECLINE); + + /* if we tried more then MAX_CONFLICTS we must limit our rate for + * acquiring and probing addresses. compliant to RFC 5227 Section 2.1.1 */ + if (acd->num_conflicts >= MAX_CONFLICTS) { + acd->state = ACD_STATE_RATE_LIMIT; + acd->ttw = (u16_t)(RATE_LIMIT_INTERVAL * ACD_TICKS_PER_SECOND); + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("acd_restart(): rate limiting initiated. too many conflicts\n")); + } + else { + /* acd should be stopped because ipaddr isn't valid any more */ + acd_stop(acd); + /* let the acd user know right away that their is a conflict detected. + * So it can restart the address acquiring process. */ + acd->acd_conflict_callback(netif, ACD_RESTART_CLIENT); + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_input(). + * + * @param netif network interface to use for acd processing + * @param hdr Incoming ARP packet + */ +void +acd_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + struct acd *acd; + ip4_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN); + + /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support + * compilers without structure packing (not using structure copy which + * breaks strict-aliasing rules). + */ + IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr); + IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr); + + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE, ("acd_arp_reply()\n")); + + /* loop over the acd's*/ + ACD_FOREACH(acd, netif->acd_list) { + switch(acd->state) { + case ACD_STATE_OFF: + case ACD_STATE_RATE_LIMIT: + default: + /* do nothing */ + break; + + case ACD_STATE_PROBE_WAIT: + case ACD_STATE_PROBING: + case ACD_STATE_ANNOUNCE_WAIT: + /* RFC 5227 Section 2.1.1: + * from beginning to after ANNOUNCE_WAIT seconds we have a conflict if + * ip.src == ipaddr (someone is already using the address) + * OR + * ip.dst == ipaddr && hw.src != own hwaddr (someone else is probing it) + */ + if ((ip4_addr_eq(&sipaddr, &acd->ipaddr)) || + (ip4_addr_isany_val(sipaddr) && + ip4_addr_eq(&dipaddr, &acd->ipaddr) && + !eth_addr_eq(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("acd_arp_reply(): Probe Conflict detected\n")); + acd_restart(netif, acd); + } + break; + + case ACD_STATE_ANNOUNCING: + case ACD_STATE_ONGOING: + case ACD_STATE_PASSIVE_ONGOING: + /* RFC 5227 Section 2.4: + * in any state we have a conflict if + * ip.src == ipaddr && hw.src != own hwaddr (someone is using our address) + */ + if (ip4_addr_eq(&sipaddr, &acd->ipaddr) && + !eth_addr_eq(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("acd_arp_reply(): Conflicting ARP-Packet detected\n")); + acd_handle_arp_conflict(netif, acd); + } + break; + } + } +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +acd_handle_arp_conflict(struct netif *netif, struct acd *acd) +{ + /* RFC5227, 2.4 "Ongoing Address Conflict Detection and Address Defense" + allows three options where: + a) means retreat on the first conflict, + b) allows to keep an already configured address when having only one + conflict in DEFEND_INTERVAL seconds and + c) the host will not give up it's address and defend it indefinitely + + We use option b) when the acd module represents the netif address, since it + helps to improve the chance that one of the two conflicting hosts may be + able to retain its address. while we are flexible enough to help network + performance + + We use option a) when the acd module does not represent the netif address, + since we cannot have the acd module announcing or restarting. This + situation occurs for the LL acd module when a routable address is used on + the netif but the LL address is still open in the background. */ + + if (acd->state == ACD_STATE_PASSIVE_ONGOING) { + /* Immediately back off on a conflict. */ + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_handle_arp_conflict(): conflict when we are in passive mode -> back off\n")); + acd_stop(acd); + acd->acd_conflict_callback(netif, ACD_DECLINE); + } + else { + if (acd->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_handle_arp_conflict(): conflict within DEFEND_INTERVAL -> retreating\n")); + + /* Active TCP sessions are aborted when removing the ip address but a bad + * connection was inevitable anyway with conflicting hosts */ + acd_restart(netif, acd); + } else { + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_handle_arp_conflict(): we are defending, send ARP Announce\n")); + etharp_acd_announce(netif, &acd->ipaddr); + acd->lastconflict = DEFEND_INTERVAL * ACD_TICKS_PER_SECOND; + } + } +} + +/** + * Put the acd module in passive ongoing conflict detection. + */ +static void +acd_put_in_passive_mode(struct netif *netif, struct acd *acd) +{ + switch(acd->state) { + case ACD_STATE_OFF: + case ACD_STATE_PASSIVE_ONGOING: + default: + /* do nothing */ + break; + + case ACD_STATE_PROBE_WAIT: + case ACD_STATE_PROBING: + case ACD_STATE_ANNOUNCE_WAIT: + case ACD_STATE_RATE_LIMIT: + acd_stop(acd); + acd->acd_conflict_callback(netif, ACD_DECLINE); + break; + + case ACD_STATE_ANNOUNCING: + case ACD_STATE_ONGOING: + acd->state = ACD_STATE_PASSIVE_ONGOING; + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_put_in_passive_mode()\n")); + break; + } +} + +/** + * @ingroup acd + * Inform the ACD modules of address changes + * + * @param netif network interface on which the address is changing + * @param old_addr old ip address + * @param new_addr new ip address + */ +void +acd_netif_ip_addr_changed(struct netif *netif, const ip_addr_t *old_addr, + const ip_addr_t *new_addr) +{ + struct acd *acd; + + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_netif_ip_addr_changed(): Address changed\n")); + + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_netif_ip_addr_changed(): old address = %s\n", ipaddr_ntoa(old_addr))); + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_netif_ip_addr_changed(): new address = %s\n", ipaddr_ntoa(new_addr))); + + /* If we change from ANY to an IP or from an IP to ANY we do nothing */ + if (ip_addr_isany(old_addr) || ip_addr_isany(new_addr)) { + return; + } + + ACD_FOREACH(acd, netif->acd_list) { + /* Find ACD module of old address */ + if(ip4_addr_eq(&acd->ipaddr, ip_2_ip4(old_addr))) { + /* Did we change from a LL address to a routable address? */ + if (ip_addr_islinklocal(old_addr) && !ip_addr_islinklocal(new_addr)) { + LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("acd_netif_ip_addr_changed(): changed from LL to routable address\n")); + /* Put the module in passive conflict detection mode */ + acd_put_in_passive_mode(netif, acd); + } + } + } +} + +#endif /* LWIP_IPV4 && LWIP_ACD */ diff --git a/src/core/ipv4/autoip.c b/src/core/ipv4/autoip.c index 9f7139b..461a005 100644 --- a/src/core/ipv4/autoip.c +++ b/src/core/ipv4/autoip.c @@ -3,7 +3,9 @@ * AutoIP Automatic LinkLocal IP Configuration * * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. + * with RFC 3927. It uses IPv4 address conflict detection to evaluate the chosen + * address. The ACD module aims to be conform to RFC 5227. + * RFC 5227 is extracted out of RFC 3927 so the acd module fits nicely in autoip. * * @defgroup autoip AUTOIP * @ingroup ip4 @@ -11,10 +13,6 @@ * 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(). @@ -65,21 +63,12 @@ #include "lwip/ip_addr.h" #include "lwip/netif.h" #include "lwip/autoip.h" +#include "lwip/acd.h" #include "lwip/etharp.h" #include "lwip/prot/autoip.h" #include -/** 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. @@ -90,9 +79,12 @@ ((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); +/* Function definitions */ +static void autoip_restart(struct netif *netif); +static void autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr); +static err_t autoip_bind(struct netif *netif); +static void autoip_conflict_callback(struct netif *netif, + acd_callback_enum_t state); /** * @ingroup autoip @@ -117,6 +109,23 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); } +/** + * @ingroup autoip + * Remove a struct autoip previously set to the netif using autoip_set_struct() + * + * @param netif the netif for which to set the struct autoip + */ +void +autoip_remove_struct(struct netif *netif) +{ + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("netif has no struct autoip set", + netif_autoip_data(netif) != NULL); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, NULL); +} + /** Restart AutoIP client and check the next address (conflict detected) * * @param netif The netif under AutoIP control @@ -129,35 +138,6 @@ autoip_restart(struct netif *netif) 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 @@ -195,29 +175,6 @@ autoip_create_addr(struct netif *netif, ip4_addr_t *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 @@ -230,6 +187,8 @@ autoip_bind(struct netif *netif) struct autoip *autoip = netif_autoip_data(netif); ip4_addr_t sn_mask, gw_addr; + autoip->state = AUTOIP_STATE_BOUND; + 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, @@ -245,6 +204,35 @@ autoip_bind(struct netif *netif) return ERR_OK; } +/** +* Handle conflict information from ACD module +* +* @param netif network interface to handle conflict information on +* @param state acd_callback_enum_t + */ +static void +autoip_conflict_callback(struct netif *netif, acd_callback_enum_t state) +{ + struct autoip *autoip = netif_autoip_data(netif); + + switch (state) { + case ACD_IP_OK: + autoip_bind(netif); + break; + case ACD_RESTART_CLIENT: + autoip_restart(netif); + break; + case ACD_DECLINE: + /* "delete" conflicting address so a new one will be selected in + * autoip_start() */ + ip4_addr_set_any(&autoip->llipaddr); + autoip_stop(netif); + break; + default: + break; + } +} + /** * @ingroup autoip * Start AutoIP client @@ -260,14 +248,6 @@ autoip_start(struct netif *netif) LWIP_ASSERT_CORE_LOCKED(); 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, @@ -280,62 +260,73 @@ autoip_start(struct netif *netif) } /* 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; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip\n")); } - autoip_create_addr(netif, &(autoip->llipaddr)); - autoip_start_probing(netif); + if (autoip->state == AUTOIP_STATE_OFF) { + 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)); + + /* add acd struct to list*/ + acd_add(netif, &autoip->acd, autoip_conflict_callback); + + /* In accordance to RFC3927 section 2.1: + * Keep using the same link local address as much as possible. + * Only when there is none or when there was a conflict, select a new one. + */ + if (!ip4_addr_islinklocal(&autoip->llipaddr)) { + autoip_create_addr(netif, &(autoip->llipaddr)); + } + autoip->state = AUTOIP_STATE_CHECKING; + acd_start(netif, &autoip->acd, autoip->llipaddr); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(): already started on netif=%p %c%c%"U16_F"\n", + (void *)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + } return result; } -static void -autoip_start_probing(struct netif *netif) + +/** + * Handle a possible change in the network configuration: link up + * + * If there is an AutoIP address configured and AutoIP is not in cooperation + * with DHCP, start probing for previous address. + */ +void +autoip_network_changed_link_up(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; + if (autoip && (autoip->state != AUTOIP_STATE_OFF) && !LWIP_DHCP_AUTOIP_COOP) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_network_changed_link_up(): start acd\n")); + autoip->state = AUTOIP_STATE_CHECKING; + /* Start acd check again for the last used address */ + acd_start(netif, &autoip->acd, autoip->llipaddr); } } /** - * Handle a possible change in the network configuration. + * Handle a possible change in the network configuration: link down * - * If there is an AutoIP address configured, take the interface down - * and begin probing with the same address. + * If there is an AutoIP address configured and AutoIP is in cooperation + * with DHCP, then stop the autoip module. When the link goes up, we do not want + * the autoip module to start again. DHCP will initiate autoip when needed. */ void -autoip_network_changed(struct netif *netif) +autoip_network_changed_link_down(struct netif *netif) { struct autoip *autoip = netif_autoip_data(netif); - if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { - autoip_start_probing(netif); + if (autoip && (autoip->state != AUTOIP_STATE_OFF) && LWIP_DHCP_AUTOIP_COOP) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_network_changed_link_down(): stop autoip\n")); + autoip_stop(netif); } } @@ -356,172 +347,33 @@ autoip_stop(struct netif *netif) if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); } + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,("autoip_stop()\n")); } return ERR_OK; } -/** - * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds - */ -void -autoip_tmr(void) -{ - struct netif *netif; - /* loop through netif's */ - NETIF_FOREACH(netif) { - 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; - } - } - } -} - -/** - * 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; - SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN); - - /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). - */ - IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr); - IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&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_isany_val(sipaddr) && - ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Probe Conflict detected\n")); - 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), + * @return 1 if AutoIP supplied netif->ip_addr (state BOUND), * 0 otherwise */ u8_t -autoip_supplied_address(const struct netif *netif) +autoip_supplied_address(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; + struct autoip *autoip = netif_autoip_data(netif); + return (autoip != NULL) + && (ip4_addr_eq(netif_ip4_addr(netif), &(autoip->llipaddr))) + && (autoip->state == AUTOIP_STATE_BOUND); } 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)); + return (autoip != NULL) + && (ip4_addr_eq(addr, &(autoip->llipaddr))) + && (autoip->state == AUTOIP_STATE_BOUND); } #endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/src/core/ipv4/dhcp.c b/src/core/ipv4/dhcp.c index 76b9f68..12e0068 100644 --- a/src/core/ipv4/dhcp.c +++ b/src/core/ipv4/dhcp.c @@ -75,6 +75,7 @@ #include "lwip/def.h" #include "lwip/dhcp.h" #include "lwip/autoip.h" +#include "lwip/acd.h" #include "lwip/dns.h" #include "lwip/etharp.h" #include "lwip/prot/dhcp.h" @@ -92,6 +93,46 @@ #define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) do { LWIP_UNUSED_ARG(msg); } while(0) #endif +/** DHCP_ADD_EXTRA_REQUEST_OPTIONS: Additional options added to the list of options + * that the client requests from the servers (opt 55: DHCP_OPTION_PARAMETER_REQUEST_LIST) + * If additional options are requested, define this macro as a comma separated list, with leading comma. + * This macro is useful for example when requested vendor specific ids (VCI/VSI options), here is an example + * of requesting the VSI option (option 43) (yes, the notation is a bit strange, but it works :) + * (NOTE: the space between # and define is required because of doxygen...) + * # define DHCP_ADD_EXTRA_REQUEST_OPTIONS ,43 + */ +#ifndef DHCP_ADD_EXTRA_REQUEST_OPTIONS +#define DHCP_ADD_EXTRA_REQUEST_OPTIONS +#endif + +/** DHCP_DEFINE_CUSTOM_TIMEOUTS: if this is defined then you can customize various DHCP timeouts using these macros: + - DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE() to adjust the t0 lease timeout from the offered value + - DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW() same for t1 renew + - DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND() same for t2 rebind + - DHCP_NEXT_TIMEOUT_THRESHOLD to adjust the period of the next timeout + - DHCP_REQUEST_BACKOFF_SEQUENCE to adjust back-off times based on DHCP request attempts + */ +#ifndef DHCP_DEFINE_CUSTOM_TIMEOUTS +#define SET_TIMEOUT_FROM_OFFERED(result, offered, min, max) do { \ + u32_t timeout = (offered + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; \ + if (timeout > max) { \ + timeout = max; \ + } \ + if (timeout == min) { \ + timeout = 1; \ + } \ + result = (dhcp_timeout_t)timeout; \ +} while(0) + +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered_t0_lease, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered_t1_renew, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered_t2_rebind, 0, 0xffff) + +#define DHCP_NEXT_TIMEOUT_THRESHOLD ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS) +#define DHCP_REQUEST_BACKOFF_SEQUENCE(tries) (u16_t)(( (tries) < 6 ? 1 << (tries) : 60) * 1000) + +#endif /* DHCP_DEFINE_CUSTOM_TIMEOUTS */ + /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) */ @@ -159,11 +200,11 @@ enum dhcp_option_idx { /** 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]; +static 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_rx_options_given[DHCP_OPTION_IDX_MAX]; static u8_t dhcp_discover_request_options[] = { DHCP_OPTION_SUBNET_MASK, @@ -175,6 +216,7 @@ static u8_t dhcp_discover_request_options[] = { #if LWIP_DHCP_GET_NTP_SRV , DHCP_OPTION_NTP #endif /* LWIP_DHCP_GET_NTP_SRV */ + DHCP_ADD_EXTRA_REQUEST_OPTIONS }; #ifdef DHCP_GLOBAL_XID @@ -196,9 +238,9 @@ static u8_t dhcp_pcb_refcount; 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 +#if LWIP_DHCP_DOES_ACD_CHECK static err_t dhcp_decline(struct netif *netif); -#endif /* DHCP_DOES_ARP_CHECK */ +#endif /* LWIP_DHCP_DOES_ACD_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); @@ -294,13 +336,56 @@ dhcp_handle_nak(struct netif *netif) dhcp_discover(netif); } -#if DHCP_DOES_ARP_CHECK +#if LWIP_DHCP_DOES_ACD_CHECK +/** +* Handle conflict information from ACD module +* +* @param netif network interface to handle conflict information on +* @param state acd_callback_enum_t + */ +static void +dhcp_conflict_callback(struct netif *netif, acd_callback_enum_t state) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + u16_t msecs; + + LWIP_ASSERT("DHCP should be enabled at this point, but it is not!", + (dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)); + + switch (state) { + case ACD_IP_OK: + dhcp_bind(netif); + break; + case ACD_RESTART_CLIENT: + /* wait 10s before restarting + * According to RFC2131 section 3.1 point 5: + * If the client detects that the address is already in use (e.g., through + * the use of ARP), the client MUST send a DHCPDECLINE message to the + * server and restarts the configuration process. The client SHOULD wait + * a minimum of ten seconds before restarting the configuration process to + * avoid excessive network traffic in case of looping. */ + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + msecs = 10 * 1000; + dhcp->request_timeout = (u16_t)((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)); + break; + case ACD_DECLINE: + /* remove IP address from interface + * (prevents routing from selecting this interface) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + /* Let the DHCP server know we will not use the address */ + dhcp_decline(netif); + break; + default: + break; + } +} + /** * 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. + * It does this according to the address conflict detection method described in + * RFC5227. * * @param netif the netif under DHCP control */ @@ -308,25 +393,15 @@ 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 = (u16_t)((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)); + + /* start ACD module */ + acd_start(netif, &dhcp->acd, dhcp->offered_ip_addr); } -#endif /* DHCP_DOES_ARP_CHECK */ +#endif /* LWIP_DHCP_DOES_ACD_CHECK */ /** * Remember the configuration offered by a DHCP server. @@ -520,19 +595,6 @@ dhcp_timeout(struct netif *netif) dhcp_release_and_stop(netif); dhcp_start(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); @@ -563,8 +625,8 @@ dhcp_t1_timeout(struct netif *netif) 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 = (u16_t)((dhcp->t2_timeout - dhcp->lease_used) / 2); + if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t1_renew_time = (dhcp_timeout_t)((dhcp->t2_timeout - dhcp->lease_used) / 2); } } } @@ -589,8 +651,8 @@ dhcp_t2_timeout(struct netif *netif) 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 = (u16_t)((dhcp->t0_timeout - dhcp->lease_used) / 2); + if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t2_rebind_time = (dhcp_timeout_t)((dhcp->t0_timeout - dhcp->lease_used) / 2); } } } @@ -655,9 +717,9 @@ dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in) 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; + dhcp->flags |= DHCP_FLAG_SUBNET_MASK_GIVEN; } else { - dhcp->subnet_mask_given = 0; + dhcp->flags &= ~DHCP_FLAG_SUBNET_MASK_GIVEN; } /* gateway router */ @@ -701,6 +763,8 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) /* clear data structure */ memset(dhcp, 0, sizeof(struct dhcp)); + /* mark this as externally allocated */ + dhcp->flags |= DHCP_FLAG_EXTERNAL_MEM; /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); } @@ -716,11 +780,15 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) */ void dhcp_cleanup(struct netif *netif) { + struct dhcp *dhcp; LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT("netif != NULL", netif != NULL); - if (netif_dhcp_data(netif) != NULL) { - mem_free(netif_dhcp_data(netif)); + dhcp = netif_dhcp_data(netif); + if (dhcp != NULL) { + if (!(dhcp->flags & DHCP_FLAG_EXTERNAL_MEM)) { + mem_free(dhcp); + } netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); } } @@ -767,7 +835,7 @@ dhcp_start(struct netif *netif) /* 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")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp\n")); /* already has DHCP client attached */ } else { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); @@ -782,6 +850,13 @@ dhcp_start(struct netif *netif) memset(dhcp, 0, sizeof(struct dhcp)); /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + +#if LWIP_DHCP_DOES_ACD_CHECK + /* add acd struct to list*/ + acd_add(netif, &dhcp->acd, dhcp_conflict_callback); +#endif /* LWIP_DHCP_DOES_ACD_CHECK */ + + 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 */ @@ -860,7 +935,7 @@ dhcp_inform(struct netif *netif) * address is still valid. */ void -dhcp_network_changed(struct netif *netif) +dhcp_network_changed_link_up(struct netif *netif) { struct dhcp *dhcp = netif_dhcp_data(netif); @@ -883,12 +958,6 @@ dhcp_network_changed(struct netif *netif) /* 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); @@ -896,37 +965,7 @@ dhcp_network_changed(struct netif *netif) } } -#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); - } - } -} - +#if LWIP_DHCP_DOES_ACD_CHECK /** * Decline an offered lease. * @@ -941,12 +980,12 @@ dhcp_decline(struct netif *netif) { struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; - u16_t msecs; struct pbuf *p_out; u16_t options_out_len; 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 */ p_out = dhcp_create_msg(netif, dhcp, DHCP_DECLINE, &options_out_len); if (p_out != NULL) { @@ -966,15 +1005,9 @@ dhcp_decline(struct netif *netif) ("dhcp_decline: could not allocate DHCP request\n")); result = ERR_MEM; } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = 10 * 1000; - dhcp->request_timeout = (u16_t)((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 */ +#endif /* LWIP_DHCP_DOES_ACD_CHECK */ /** @@ -994,6 +1027,12 @@ dhcp_discover(struct netif *netif) LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES) { + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + ip4_addr_set_any(&dhcp->offered_ip_addr); dhcp_set_state(dhcp, DHCP_STATE_SELECTING); /* create and initialize the DHCP message header */ @@ -1005,6 +1044,10 @@ dhcp_discover(struct netif *netif) options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif)); +#if LWIP_NETIF_HOSTNAME && LWIP_DHCP_DISCOVER_ADD_HOSTNAME + options_out_len = dhcp_option_hostname(options_out_len, msg_out->options, netif); +#endif /* LWIP NETIF HOSTNAME && LWIP_DHCP_DISCOVER_ADD_HOSTNAME */ + options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]); @@ -1014,22 +1057,17 @@ dhcp_discover(struct netif *netif) LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)\n")); udp_sendto_if_src(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()\n")); pbuf_free(p_out); 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 = (u16_t)((dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000); + msecs = DHCP_REQUEST_BACKOFF_SEQUENCE(dhcp->tries); dhcp->request_timeout = (u16_t)((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; @@ -1044,7 +1082,6 @@ dhcp_discover(struct netif *netif) 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;); @@ -1058,14 +1095,7 @@ dhcp_bind(struct netif *netif) 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; - } + DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(dhcp->t0_timeout, dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease * 1000)); } @@ -1073,28 +1103,14 @@ dhcp_bind(struct netif *netif) 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; - } + DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(dhcp->t1_timeout, dhcp); 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; - } + DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(dhcp->t2_timeout, dhcp); 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; } @@ -1104,7 +1120,7 @@ dhcp_bind(struct netif *netif) dhcp->t1_timeout = 0; } - if (dhcp->subnet_mask_given) { + if (dhcp->flags & DHCP_FLAG_SUBNET_MASK_GIVEN) { /* copy offered network mask */ ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); } else { @@ -1121,13 +1137,6 @@ dhcp_bind(struct netif *netif) ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); -#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 @@ -1371,12 +1380,10 @@ dhcp_release_and_stop(struct netif *netif) dhcp_set_state(dhcp, DHCP_STATE_OFF); } -#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 */ +#if LWIP_DHCP_DOES_ACD_CHECK + /* stop acd because we may be in checking state and the callback would trigger a bind */ + acd_remove(netif, &dhcp->acd); +#endif if (dhcp->pcb_allocated != 0) { dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ @@ -1570,7 +1577,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp) } 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)); */ + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F"\n", msg_offset, q->len)); */ decode_len = len; switch (op) { /* case(DHCP_OPTION_END): handled above */ @@ -1593,7 +1600,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp) /* special case: there might be more than one server */ LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); /* limit number of DNS servers */ - decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_PROVIDE_DNS_SERVERS); LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_DNS_SERVER; break; @@ -1744,7 +1751,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp) /* make sure the string is really NULL-terminated */ dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; } -#endif /* LWIP_DHCP_BOOTP_FILE */ +#endif /* LWIP_DHCP_BOOTP_FILE */ return ERR_OK; } @@ -1823,10 +1830,11 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, /* 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) { + /* in requesting state or just reconnected to the network? */ + if ((dhcp->state == DHCP_STATE_REQUESTING) || + (dhcp->state == DHCP_STATE_REBOOTING)) { dhcp_handle_ack(netif, msg_in); -#if DHCP_DOES_ARP_CHECK +#if LWIP_DHCP_DOES_ACD_CHECK if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { /* check if the acknowledged lease address is already in use */ dhcp_check(netif); @@ -1839,8 +1847,8 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, dhcp_bind(netif); #endif } - /* already bound to the given lease address? */ - else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || + /* already bound to the given lease address and using it? */ + else if ((dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING)) { dhcp_handle_ack(netif, msg_in); dhcp_bind(netif); diff --git a/src/core/ipv4/etharp.c b/src/core/ipv4/etharp.c index c3a5a10..3092dc9 100644 --- a/src/core/ipv4/etharp.c +++ b/src/core/ipv4/etharp.c @@ -7,7 +7,7 @@ * 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 + * Gratuitous ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 * if an interface calls etharp_gratuitous(our_netif) upon address change. */ @@ -52,6 +52,7 @@ #include "lwip/snmp.h" #include "lwip/dhcp.h" #include "lwip/autoip.h" +#include "lwip/acd.h" #include "lwip/prot/iana.h" #include "netif/ethernet.h" @@ -141,7 +142,7 @@ static err_t etharp_raw(struct netif *netif, /** * Free a complete queue of etharp entries * - * @param q a qeueue of etharp_q_entry's to free + * @param q a queue of etharp_q_entry's to free */ static void free_etharp_q(struct etharp_q_entry *q) @@ -291,7 +292,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) 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 (ipaddr && ip4_addr_eq(ipaddr, &arp_table[i].ipaddr) #if ETHARP_TABLE_MATCH_NETIF && ((netif == NULL) || (netif == arp_table[i].netif)) #endif /* ETHARP_TABLE_MATCH_NETIF */ @@ -643,7 +644,7 @@ 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; + u8_t for_us, from_us; LWIP_ASSERT_CORE_LOCKED(); @@ -666,12 +667,16 @@ etharp_input(struct pbuf *p, struct netif *netif) } 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 */ +#if LWIP_ACD + /* We have to check if a host already has configured our ip address and + * continuously check if there is a host with this IP-address so we can + * detect collisions. + * acd_arp_reply ensures the detection of conflicts. It will handle possible + * defending or retreating and will make sure a new IP address is selected. + * etharp_input does not need to handle packets that originate "from_us". + */ + acd_arp_reply(netif, hdr); +#endif /* LWIP_ACD */ /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without * structure packing (not using structure copy which breaks strict-aliasing rules). */ @@ -681,9 +686,12 @@ etharp_input(struct pbuf *p, struct netif *netif) /* this interface is not configured? */ if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { for_us = 0; + from_us = 0; } else { /* ARP packet directed to us? */ - for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); + for_us = (u8_t)ip4_addr_eq(&dipaddr, netif_ip4_addr(netif)); + /* ARP packet from us? */ + from_us = (u8_t)ip4_addr_eq(&sipaddr, netif_ip4_addr(netif)); } /* ARP message directed to us? @@ -704,7 +712,7 @@ etharp_input(struct pbuf *p, struct netif *netif) LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); /* ARP request for our address? */ - if (for_us) { + if (for_us && !from_us) { /* send ARP response */ etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &hdr->shwaddr, @@ -724,13 +732,6 @@ etharp_input(struct pbuf *p, struct netif *netif) 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))); @@ -822,7 +823,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) netif_addr_idx_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)) && + if (!ip4_addr_net_eq(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && !ip4_addr_islinklocal(ipaddr)) { #if LWIP_AUTOIP struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr *, q->payload); @@ -862,7 +863,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) #if ETHARP_TABLE_MATCH_NETIF (arp_table[etharp_cached_entry].netif == netif) && #endif - (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + (ip4_addr_eq(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); @@ -879,7 +880,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) #if ETHARP_TABLE_MATCH_NETIF (arp_table[i].netif == netif) && #endif - (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + (ip4_addr_eq(dst_addr, &arp_table[i].ipaddr))) { /* found an existing, stable entry */ ETHARP_SET_ADDRHINT(netif, i); return etharp_output_to_arp_index(netif, q, i); @@ -1014,7 +1015,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) * new PBUF_RAM. See the definition of PBUF_NEEDS_COPY for details. */ p = q; while (p) { - LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == NULL)); if (PBUF_NEEDS_COPY(p)) { copy_needed = 1; break; @@ -1038,7 +1039,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) 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->next = NULL; new_entry->p = p; if (arp_table[i].q != NULL) { /* queue was already existent, append the new entry to the end */ @@ -1209,4 +1210,42 @@ etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) return etharp_request_dst(netif, ipaddr, ðbroadcast); } +#if LWIP_ACD +/** + * Send an ARP request packet probing for an ipaddr. + * Used to send probe messages for address conflict detection. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address to probe + * @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_acd_probe(struct netif *netif, const ip4_addr_t *ipaddr) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP4_ADDR_ANY4, ðzero, + ipaddr, ARP_REQUEST); +} + +/** + * Send an ARP request packet announcing an ipaddr. + * Used to send announce messages for address conflict detection. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address to announce + * @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_acd_announce(struct netif *netif, const ip4_addr_t *ipaddr) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, ipaddr, ðzero, + ipaddr, ARP_REQUEST); +} +#endif /* LWIP_ACD */ + #endif /* LWIP_IPV4 && LWIP_ARP */ diff --git a/src/core/ipv4/icmp.c b/src/core/ipv4/icmp.c index 59b493a..f35ff4b 100644 --- a/src/core/ipv4/icmp.c +++ b/src/core/ipv4/icmp.c @@ -171,7 +171,7 @@ icmp_input(struct pbuf *p, struct netif *inp) 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")); + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header\n")); pbuf_free(r); goto icmperr; } @@ -179,13 +179,13 @@ icmp_input(struct pbuf *p, struct netif *inp) MEMCPY(r->payload, iphdr_in, hlen); /* switch r->payload back to icmp header (cannot fail) */ if (pbuf_remove_header(r, hlen)) { - LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); + LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed", 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")); + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed\n")); pbuf_free(r); goto icmperr; } @@ -196,7 +196,7 @@ icmp_input(struct pbuf *p, struct netif *inp) } else { /* restore p->payload to point to icmp header (cannot fail) */ if (pbuf_remove_header(p, hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN)) { - LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + LWIP_ASSERT("icmp_input: restoring original p->payload failed", 0); goto icmperr; } } @@ -206,13 +206,14 @@ icmp_input(struct pbuf *p, struct netif *inp) * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ iecho = (struct icmp_echo_hdr *)p->payload; if (pbuf_add_header(p, hlen)) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet\n")); } 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); + p->if_idx = NETIF_NO_INDEX; /* we're reusing this pbuf, so reset its if_idx */ #if CHECKSUM_GEN_ICMP IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { /* adjust the checksum */ @@ -341,8 +342,7 @@ 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; + struct icmp_hdr *icmphdr; ip4_addr_t iphdr_src; struct netif *netif; u16_t response_pkt_len; @@ -357,31 +357,29 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code) } /* ICMP header + part of original packet */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + response_pkt_len, PBUF_RAM); + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_hdr) + response_pkt_len, PBUF_RAM); if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_send_response: 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) + response_pkt_len))); + (q->len >= (sizeof(struct icmp_hdr) + response_pkt_len))); iphdr = (struct ip_hdr *)p->payload; - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_send_response: Sending ICMP type %02X for packet from ", type)); 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 = (struct icmp_hdr *)q->payload; icmphdr->type = type; icmphdr->code = code; - icmphdr->id = 0; - icmphdr->seqno = 0; + icmphdr->data = 0; /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, - response_pkt_len); + pbuf_copy_partial_pbuf(q, p, response_pkt_len, sizeof(struct icmp_hdr)); ip4_addr_copy(iphdr_src, iphdr->src); #ifdef LWIP_HOOK_IP4_ROUTE_SRC diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index b655aa3..a74df16 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -220,7 +220,7 @@ 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)) { + if (ip4_addr_eq(&(group->group_address), addr)) { return group; } group = group->next; @@ -266,13 +266,13 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) if (list_head == NULL) { /* this is the first entry in linked list */ LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", - (ip4_addr_cmp(addr, &allsystems) != 0)); + (ip4_addr_eq(addr, &allsystems) != 0)); group->next = NULL; netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); } else { /* append _after_ first entry */ LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", - (ip4_addr_cmp(addr, &allsystems) == 0)); + (ip4_addr_eq(addr, &allsystems) == 0)); group->next = list_head->next; list_head->next = group; } @@ -366,7 +366,7 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) 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)) { + if ((ip4_addr_eq(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))); @@ -395,7 +395,7 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) 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_val(IGMP_DEBUG, igmp->igmp_group_address); - if (ip4_addr_cmp(dest, &allsystems)) { + if (ip4_addr_eq(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 */ @@ -455,12 +455,12 @@ igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) /* 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;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_eq(groupaddr, &allsystems)), return ERR_VAL;); /* loop through netif's */ NETIF_FOREACH(netif) { /* Should we join this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_eq(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 */ @@ -490,7 +490,7 @@ igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) /* 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;); + LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_eq(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;); @@ -552,12 +552,12 @@ igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) /* 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;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_eq(groupaddr, &allsystems)), return ERR_VAL;); /* loop through netif's */ NETIF_FOREACH(netif) { /* Should we leave this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_eq(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 */ @@ -586,7 +586,7 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) /* 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;); + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_eq(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;); @@ -669,7 +669,7 @@ 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)))) { + (!(ip4_addr_eq(&(group->group_address), &allsystems)))) { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); ip4_addr_debug_print_val(IGMP_DEBUG, group->group_address); LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void *)netif)); diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 26c26a9..e044bff 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -171,12 +171,12 @@ ip4_route(const ip4_addr_t *dest) /* 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))) { + if (ip4_addr_net_eq(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))) { + if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_eq(dest, netif_ip4_gw(netif))) { /* return netif on which to forward IP packet */ return netif; } @@ -184,10 +184,10 @@ ip4_route(const ip4_addr_t *dest) } #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - /* loopif is disabled, looopback traffic is passed through any netif */ + /* loopif is disabled, loopback traffic is passed through any netif */ if (ip4_addr_isloopback(dest)) { /* don't check for link on loopback traffic */ - if (netif_default != NULL && netif_is_up(netif_default)) { + if ((netif_default != NULL) && netif_is_up(netif_default)) { return netif_default; } /* default netif is not up, just use any netif for loopback traffic */ @@ -336,6 +336,40 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) IPH_CHKSUM_SET(iphdr, (u16_t)(IPH_CHKSUM(iphdr) + PP_HTONS(0x100))); } + /* Take care of setting checksums to 0 for checksum offload netifs */ + if (CHECKSUM_GEN_IP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP)) { + IPH_CHKSUM_SET(iphdr, 0); + } + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif + case IP_PROTO_UDP: + if (CHECKSUM_GEN_UDP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_UDP)) { + ((struct udp_hdr *)((u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0; + } + break; +#endif +#if LWIP_TCP + case IP_PROTO_TCP: + if (CHECKSUM_GEN_TCP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_TCP)) { + ((struct tcp_hdr *)((u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0; + } + break; +#endif +#if LWIP_ICMP + case IP_PROTO_ICMP: + if (CHECKSUM_GEN_ICMP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP)) { + ((struct icmp_hdr *)((u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0; + } + break; +#endif + default: + /* there's really nothing to do here other than satisfying 'switch-default' */ + break; + } + 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()))); @@ -382,7 +416,7 @@ ip4_input_accept(struct netif *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)) || + if (ip4_addr_eq(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 @@ -522,7 +556,7 @@ ip4_input(struct pbuf *p, struct netif *inp) /* 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) && + if (ip4_addr_eq(ip4_current_dest_addr(), &allsystems) && ip4_addr_isany(ip4_current_src_addr())) { check_ip_src = 0; } @@ -981,13 +1015,13 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d ip4_debug_print(p); #if ENABLE_LOOPBACK - if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) + if (ip4_addr_eq(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()")); + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()\n")); return netif_loop_output(netif, p); } #if LWIP_MULTICAST_TX_OPTIONS diff --git a/src/core/ipv4/ip4_addr.c b/src/core/ipv4/ip4_addr.c index f99d8dd..79127ac 100644 --- a/src/core/ipv4/ip4_addr.c +++ b/src/core/ipv4/ip4_addr.c @@ -73,7 +73,7 @@ ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) } 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)) + } else if (ip4_addr_net_eq(&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))))) { diff --git a/src/core/ipv4/ip4_frag.c b/src/core/ipv4/ip4_frag.c index a445530..5303144 100644 --- a/src/core/ipv4/ip4_frag.c +++ b/src/core/ipv4/ip4_frag.c @@ -106,8 +106,8 @@ PACK_STRUCT_END #endif #define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ - (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ - ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + (ip4_addr_eq(&(iphdrA)->src, &(iphdrB)->src) && \ + ip4_addr_eq(&(iphdrA)->dest, &(iphdrB)->dest) && \ IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 /* global variables */ diff --git a/src/core/ipv6/dhcp6.c b/src/core/ipv6/dhcp6.c index 41444a4..e6a7e64 100644 --- a/src/core/ipv6/dhcp6.c +++ b/src/core/ipv6/dhcp6.c @@ -16,8 +16,8 @@ * - only start requests if a valid local address is available on the netif * - only start information requests if required (not for every RA) * - * dhcp6_enable_stateful() enables stateful DHCPv6 for a netif (stateless disabled)\n - * dhcp6_enable_stateless() enables stateless DHCPv6 for a netif (stateful disabled)\n + * dhcp6_enable_stateful() enables stateful DHCPv6 for a netif (stateless disabled)
+ * dhcp6_enable_stateless() enables stateless DHCPv6 for a netif (stateful disabled)
* dhcp6_disable() disable DHCPv6 for a netif * * When enabled, requests are only issued after receipt of RA with the @@ -240,7 +240,7 @@ dhcp6_get_struct(struct netif *netif, const char *dbg_requester) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP6, NULL); return NULL; } - LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("%s: allocated dhcp6", dbg_requester)); + LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("%s: allocated dhcp6\n", dbg_requester)); dhcp6->pcb_allocated = 1; } return dhcp6; @@ -299,7 +299,7 @@ err_t dhcp6_enable_stateful(struct netif *netif) { LWIP_UNUSED_ARG(netif); - LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("stateful dhcp6 not implemented yet")); + LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("stateful dhcp6 not implemented yet\n")); return ERR_VAL; } @@ -324,12 +324,12 @@ dhcp6_enable_stateless(struct netif *netif) return ERR_MEM; } if (dhcp6_stateless_enabled(dhcp6)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp6_enable_stateless(): stateless DHCPv6 already enabled")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp6_enable_stateless(): stateless DHCPv6 already enabled\n")); return ERR_OK; } else if (dhcp6->state != DHCP6_STATE_OFF) { /* stateful running */ /* @todo: stop stateful once it is implemented */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp6_enable_stateless(): switching from stateful to stateless DHCPv6")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp6_enable_stateless(): switching from stateful to stateless DHCPv6\n")); } LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp6_enable_stateless(): stateless DHCPv6 enabled\n")); dhcp6_set_state(dhcp6, DHCP6_STATE_STATELESS_IDLE, "dhcp6_enable_stateless"); @@ -453,14 +453,14 @@ dhcp6_information_request(struct netif *netif, struct dhcp6 *dhcp6) { const u16_t requested_options[] = { #if LWIP_DHCP6_PROVIDE_DNS_SERVERS - DHCP6_OPTION_DNS_SERVERS, + DHCP6_OPTION_DNS_SERVERS, DHCP6_OPTION_DOMAIN_LIST #endif #if LWIP_DHCP6_GET_NTP_SRV , DHCP6_OPTION_SNTP_SERVERS #endif }; - + u16_t msecs; struct pbuf *p_out; u16_t options_out_len; @@ -579,7 +579,7 @@ dhcp6_handle_config_reply(struct netif *netif, struct pbuf *p_msg_in) } #endif /* LWIP_IPV6_DHCP6_STATELESS */ -/** This function is called from nd6 module when an RA messsage is received +/** This function is called from nd6 module when an RA message is received * It triggers DHCPv6 requests (if enabled). */ void @@ -645,7 +645,7 @@ dhcp6_parse_reply(struct pbuf *p, struct dhcp6 *dhcp6) /* overflow */ return ERR_BUF; } - /* copy option + length, might be split accross pbufs */ + /* copy option + length, might be split across pbufs */ op_len = (u8_t *)pbuf_get_contiguous(p, op_len_buf, 4, 4, offset); if (op_len == NULL) { /* failed to get option and length */ diff --git a/src/core/ipv6/icmp6.c b/src/core/ipv6/icmp6.c index 4fd1021..ed0bd7b 100644 --- a/src/core/ipv6/icmp6.c +++ b/src/core/ipv6/icmp6.c @@ -388,7 +388,6 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data, struct pbuf *q; struct icmp6_hdr *icmp6hdr; u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE); - u16_t offset; /* ICMPv6 header + datalen (as much of the offending packet as possible) */ q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen, @@ -406,16 +405,8 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data, icmp6hdr->code = code; icmp6hdr->data = lwip_htonl(data); - /* copy fields from original packet (which may be a chain of pbufs) */ - offset = sizeof(struct icmp6_hdr); - while (p && datalen) { - u16_t len = LWIP_MIN(datalen, p->len); - err_t res = pbuf_take_at(q, p->payload, len, offset); - if (res != ERR_OK) break; - datalen -= len; - offset += len; - p = p->next; - } + /* copy fields from original packet */ + pbuf_copy_partial_pbuf(q, p, datalen, sizeof(struct icmp6_hdr)); /* calculate checksum */ icmp6hdr->chksum = 0; diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index 060d5f3..2c25f8a 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -166,7 +166,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp_zoneless(src, netif_ip6_addr(netif, i))) { + ip6_addr_zoneless_eq(src, netif_ip6_addr(netif, i))) { return netif; } } @@ -199,9 +199,9 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } 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)) && + ip6_addr_net_eq(dest, netif_ip6_addr(netif, i)) && (netif_ip6_addr_isstatic(netif, i) || - ip6_addr_nethostcmp(dest, netif_ip6_addr(netif, i)))) { + ip6_addr_nethost_eq(dest, netif_ip6_addr(netif, i)))) { return netif; } } @@ -222,7 +222,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } 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))) { + ip6_addr_eq(src, netif_ip6_addr(netif, i))) { return netif; } } @@ -332,8 +332,8 @@ ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) /* @todo compute the actual common bits, for longest matching prefix. */ /* We cannot count on the destination address having a proper zone * assignment, so do not compare zones in this case. */ - cand_bits = ip6_addr_netcmp_zoneless(cand_addr, dest); /* just 1 or 0 for now */ - if (cand_bits && ip6_addr_nethostcmp(cand_addr, dest)) { + cand_bits = ip6_addr_net_zoneless_eq(cand_addr, dest); /* just 1 or 0 for now */ + if (cand_bits && ip6_addr_nethost_eq(cand_addr, dest)) { return netif_ip_addr6(netif, i); /* Rule 1 */ } if ((best_addr == NULL) || /* no alternative yet */ @@ -477,7 +477,7 @@ ip6_input_accept(struct netif *netif) * scope as well (e.g., is this interface on the same link?). */ 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)) + ip6_addr_eq(ip6_current_dest_addr(), netif_ip6_addr(netif, i)) #if IPV6_CUSTOM_SCOPES && (!ip6_addr_has_zone(ip6_current_src_addr()) || ip6_addr_test_zone(ip6_current_src_addr(), netif)) @@ -611,7 +611,7 @@ ip6_input(struct pbuf *p, struct netif *inp) 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))) { + ip6_addr_solicitednode_eq(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])); @@ -703,6 +703,10 @@ ip6_input(struct pbuf *p, struct netif *inp) /* Init header length. */ hlen = hlen_tot = IP6_HLEN; + 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)); + /* Move to payload. */ pbuf_remove_header(p, IP6_HLEN); @@ -1007,9 +1011,10 @@ ip6_input(struct pbuf *p, struct netif *inp) goto ip6_input_cleanup; } - /* Returned p point to IPv6 header. + /* Returned p points to IPv6 header. * Update all our variables and pointers and continue. */ ip6hdr = (struct ip6_hdr *)p->payload; + ip_data.current_ip6_header = ip6hdr; nexth = &IP6H_NEXTH(ip6hdr); hlen = hlen_tot = IP6_HLEN; pbuf_remove_header(p, IP6_HLEN); @@ -1042,12 +1047,8 @@ ip6_input(struct pbuf *p, struct netif *inp) options_done: /* 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)); - ip_data.current_ip_header_tot_len = hlen_tot; - + #if LWIP_RAW /* p points to IPv6 header again for raw_input. */ pbuf_add_header_force(p, hlen_tot); @@ -1245,7 +1246,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, #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))) { + ip6_addr_eq(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); diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 687c02f..6e0ac86 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -46,6 +46,7 @@ #include "lwip/ip_addr.h" #include "lwip/def.h" +#include "lwip/netif.h" #include @@ -185,6 +186,17 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } ip6_addr_clear_zone(addr); +#if LWIP_IPV6_SCOPES + if (*s == '%') { + const char *scopestr = s + 1; + if (*scopestr) { + struct netif *netif = netif_find(scopestr); + if (netif) { + ip6_addr_assign_zone(addr, IP6_UNKNOWN, netif); + } + } + } +#endif } if (current_block_index != 7) { diff --git a/src/core/ipv6/ip6_frag.c b/src/core/ipv6/ip6_frag.c index 8b352f5..ba91cfd 100644 --- a/src/core/ipv6/ip6_frag.c +++ b/src/core/ipv6/ip6_frag.c @@ -162,11 +162,11 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) ipr->p = iprh->next_pbuf; /* Restore the part that we've overwritten with our helper structure, or we * might send garbage (and disclose a pointer) in the ICMPv6 reply. */ - MEMCPY(p->payload, ipr->orig_hdr, sizeof(iprh)); + MEMCPY(p->payload, ipr->orig_hdr, sizeof(*iprh)); /* 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*)ipr->iphdr))) { - LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed", 0); } else { /* Reconstruct the zoned source and destination addresses, so that we do @@ -320,8 +320,8 @@ ip6_reass(struct pbuf *p) in the reassembly buffer. If so, we proceed with copying the fragment into the buffer. */ if ((frag_hdr->_identification == ipr->identification) && - ip6_addr_cmp_packed(ip6_current_src_addr(), &(IPV6_FRAG_SRC(ipr)), ipr->src_zone) && - ip6_addr_cmp_packed(ip6_current_dest_addr(), &(IPV6_FRAG_DEST(ipr)), ipr->dest_zone)) { + ip6_addr_packed_eq(ip6_current_src_addr(), &(IPV6_FRAG_SRC(ipr)), ipr->src_zone) && + ip6_addr_packed_eq(ip6_current_dest_addr(), &(IPV6_FRAG_DEST(ipr)), ipr->dest_zone)) { IP6_FRAG_STATS_INC(ip6_frag.cachehit); break; } @@ -447,6 +447,19 @@ ip6_reass(struct pbuf *p) } } #endif /* IP_REASS_CHECK_OVERLAP */ + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + if (end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the following fragment */ + valid = 0; + } /* the new pbuf should be inserted before this */ next_pbuf = q; if (iprh_prev != NULL) { @@ -652,12 +665,13 @@ ip6_reass(struct pbuf *p) /* Move pbuf back to IPv6 header. This should never fail. */ 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); + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed", 0); pbuf_free(p); return NULL; } /* Return the pbuf chain */ + MIB2_STATS_INC(mib2.ip6reasmoks); return p; } /* the datagram is not (yet?) reassembled completely */ diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c index a9c917d..ac4fb01 100644 --- a/src/core/ipv6/mld6.c +++ b/src/core/ipv6/mld6.c @@ -5,12 +5,12 @@ * @defgroup mld6 MLD6 * @ingroup ip6 * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2.\n - * Note: The allnodes (ff01::1, ff02::1) group is assumed be received by your + * No support for MLDv2.
+ * Note: The allnodes (ff01::1, ff02::1) group is assumed be received by your * netif since it must always be received for correct IPv6 operation (e.g. SLAAC). - * Ensure the netif filters are configured accordingly!\n + * Ensure the netif filters are configured accordingly!
* The netif flags also need NETIF_FLAG_MLD6 flag set to enable MLD6 on a - * netif ("netif->flags |= NETIF_FLAG_MLD6;").\n + * netif ("netif->flags |= NETIF_FLAG_MLD6;").
* To be called from TCPIP thread. */ @@ -146,7 +146,7 @@ mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) struct mld_group *group = netif_mld6_data(ifp); while (group != NULL) { - if (ip6_addr_cmp(&(group->group_address), addr)) { + if (ip6_addr_eq(&(group->group_address), addr)) { return group; } group = group->next; diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 81992fa..f7b5f56 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -72,6 +72,18 @@ #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #endif +#if LWIP_ND6_NUM_NEIGHBORS > 127 +#error LWIP_ND6_NUM_NEIGHBORS must fit into an s8_t (max value: 127) +#endif +#if LWIP_ND6_NUM_DESTINATIONS > 32767 +#error LWIP_ND6_NUM_DESTINATIONS must fit into an s16_t (max value: 32767) +#endif +#if LWIP_ND6_NUM_PREFIXES > 127 +#error LWIP_ND6_NUM_PREFIXES must fit into an s8_t (max value: 127) +#endif +#if LWIP_ND6_NUM_ROUTERS > 127 +#error LWIP_ND6_NUM_ROUTERS must fit into an s8_t (max value: 127) +#endif /* Router tables. */ struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; @@ -83,8 +95,11 @@ struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ +#if LWIP_ND6_QUEUEING +static u8_t nd6_queue_size = 0; +#endif + /* Index for cache entries. */ -static u8_t nd6_cached_neighbor_index; static netif_addr_idx_t nd6_cached_destination_index; /* Multicast address holder. */ @@ -210,7 +225,7 @@ nd6_process_autoconfig_prefix(struct netif *netif, for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { addr_state = netif_ip6_addr_state(netif, i); if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(netif, i) && - ip6_addr_netcmp(prefix_addr, netif_ip6_addr(netif, i))) { + ip6_addr_net_eq(prefix_addr, netif_ip6_addr(netif, i))) { /* Update the valid lifetime, as per RFC 4862 Sec. 5.5.3 point (e). * The valid lifetime will never drop to zero as a result of this. */ u32_t remaining_life = netif_ip6_addr_valid_life(netif, i); @@ -258,7 +273,7 @@ nd6_process_autoconfig_prefix(struct netif *netif, free_idx = 0; for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { - if (ip6_addr_cmp(&ip6addr, netif_ip6_addr(netif, i))) { + if (ip6_addr_eq(&ip6addr, netif_ip6_addr(netif, i))) { return; /* formed address already exists */ } } else if (free_idx == 0) { @@ -338,7 +353,7 @@ nd6_input(struct pbuf *p, struct netif *inp) for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && !ip6_addr_isduplicated(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { + ip6_addr_eq(&target_address, netif_ip6_addr(inp, i))) { /* We are using a duplicate address. */ nd6_duplicate_addr_detected(inp, i); @@ -475,7 +490,7 @@ nd6_input(struct pbuf *p, struct netif *inp) if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && ip6_addr_isany(ip6_current_src_addr()))) && - ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { + ip6_addr_eq(&target_address, netif_ip6_addr(inp, i))) { accepted = 1; break; } @@ -492,7 +507,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Sender is validating this address. */ for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { + ip6_addr_eq(&target_address, netif_ip6_addr(inp, i))) { /* Send a NA back so that the sender does not use this address. */ nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { @@ -672,7 +687,7 @@ nd6_input(struct pbuf *p, struct netif *inp) case ND6_OPTION_TYPE_SOURCE_LLADDR: { struct lladdr_option *lladdr_opt; - if (option_len < sizeof(struct lladdr_option)) { + if (option_len < (ND6_LLADDR_OPTION_MIN_LENGTH + inp->hwaddr_len)) { goto lenerr_drop_free_return; } lladdr_opt = (struct lladdr_option *)buffer; @@ -782,7 +797,7 @@ nd6_input(struct pbuf *p, struct netif *inp) u8_t s; for (s = 0; s < DNS_MAX_SERVERS; s++) { const ip_addr_t *addr = dns_getserver(s); - if(ip_addr_cmp(addr, &rdnss_address)) { + if(ip_addr_eq(addr, &rdnss_address)) { dns_setserver(s, NULL); } } @@ -1032,7 +1047,7 @@ nd6_tmr(void) * its destination cache entries, as per RFC 4861 Sec. 5.3 and 6.3.5. */ s8_t j; for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) { - if (ip6_addr_cmp(&destination_cache[j].next_hop_addr, + if (ip6_addr_eq(&destination_cache[j].next_hop_addr, &default_router_list[i].neighbor_entry->next_hop_address)) { ip6_addr_set_any(&destination_cache[j].destination_addr); } @@ -1161,7 +1176,7 @@ nd6_tmr(void) /** Send a neighbor solicitation message for a specific neighbor cache entry * - * @param entry the neightbor cache entry for wich to send the message + * @param entry the neighbor cache entry for which to send the message * @param flags one of ND6_SEND_FLAG_* */ static void @@ -1191,7 +1206,7 @@ nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) int i; for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(target_addr, netif_ip6_addr(netif, i))) { + ip6_addr_net_eq(target_addr, netif_ip6_addr(netif, i))) { src_addr = netif_ip6_addr(netif, i); break; } @@ -1414,7 +1429,7 @@ nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) { s8_t i; for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + if (ip6_addr_eq(ip6addr, &(neighbor_cache[i].next_hop_address))) { return i; } } @@ -1576,7 +1591,7 @@ nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) IP6_ADDR_ZONECHECK(ip6addr); for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + if (ip6_addr_eq(ip6addr, &(destination_cache[i].destination_addr))) { return i; } } @@ -1647,7 +1662,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { if ((prefix_list[i].netif == netif) && (prefix_list[i].invalidation_timer > 0) && - ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + ip6_addr_net_eq(ip6addr, &(prefix_list[i].prefix))) { return 1; } } @@ -1658,7 +1673,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && netif_ip6_addr_isstatic(netif, i) && - ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + ip6_addr_net_eq(ip6addr, netif_ip6_addr(netif, i))) { return 1; } } @@ -1692,7 +1707,7 @@ nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) /* Look for valid routers. A reachable router is preferred. */ valid_router = -1; for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - /* Is the router netif both set and apppropriate? */ + /* Is the router netif both set and appropriate? */ if (default_router_list[i].neighbor_entry != NULL) { router_netif = default_router_list[i].neighbor_entry->netif; if ((router_netif != NULL) && (netif != NULL ? netif == router_netif : @@ -1762,7 +1777,7 @@ nd6_find_route(const ip6_addr_t *ip6addr) * matches. Pick the first one that is associated with a suitable netif. */ for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { netif = prefix_list[i].netif; - if ((netif != NULL) && ip6_addr_netcmp(&prefix_list[i].prefix, ip6addr) && + if ((netif != NULL) && ip6_addr_net_eq(&prefix_list[i].prefix, ip6addr) && netif_is_up(netif) && netif_is_link_up(netif)) { return netif; } @@ -1797,7 +1812,7 @@ nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { if ((default_router_list[i].neighbor_entry != NULL) && ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && - ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + ip6_addr_eq(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { return i; } } @@ -1847,9 +1862,9 @@ nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { /* check if router already exists (this is a special case for 2 netifs on the same subnet - e.g. wifi and cable) */ - if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ - return router_index; - } + if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ + return router_index; + } if (default_router_list[router_index].neighbor_entry == NULL) { /* remember lowest free index to create a new entry */ free_router_index = router_index; @@ -1883,7 +1898,7 @@ nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif) /* Look for prefix in list. */ for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + if ((ip6_addr_net_eq(&(prefix_list[i].prefix), prefix)) && (prefix_list[i].netif == netif)) { return i; } @@ -1940,6 +1955,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) #endif /* LWIP_HOOK_ND6_GET_GW */ s8_t i; s16_t dst_idx; + struct nd6_destination_cache_entry *dest; IP6_ADDR_ZONECHECK_NETIF(ip6addr, netif); @@ -1953,8 +1969,11 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) } #endif /* LWIP_NETIF_HWADDRHINT */ + LWIP_ASSERT("sane cache index", nd6_cached_destination_index < LWIP_ND6_NUM_DESTINATIONS); + /* Look for ip6addr in destination cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + dest = &destination_cache[nd6_cached_destination_index]; + if (ip6_addr_eq(ip6addr, &dest->destination_addr)) { /* the cached entry index is the right one! */ /* do nothing. */ ND6_STATS_INC(nd6.cachehit); @@ -1965,6 +1984,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) /* found destination entry. make it our new cached index. */ LWIP_ASSERT("type overflow", (size_t)dst_idx < NETIF_ADDR_IDX_MAX); nd6_cached_destination_index = (netif_addr_idx_t)dst_idx; + dest = &destination_cache[dst_idx]; } else { /* Not found. Create a new destination entry. */ dst_idx = nd6_new_destination_cache_entry(); @@ -1972,72 +1992,71 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) /* got new destination entry. make it our new cached index. */ LWIP_ASSERT("type overflow", (size_t)dst_idx < NETIF_ADDR_IDX_MAX); nd6_cached_destination_index = (netif_addr_idx_t)dst_idx; + dest = &destination_cache[dst_idx]; } else { /* Could not create a destination cache entry. */ return ERR_MEM; } /* Copy dest address to destination cache. */ - ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + ip6_addr_set(&dest->destination_addr, ip6addr); /* Now find the next hop. is it a neighbor? */ if (ip6_addr_islinklocal(ip6addr) || nd6_is_prefix_in_netif(ip6addr, netif)) { /* Destination in local link. */ - destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif); - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); + dest->pmtu = netif_mtu6(netif); + ip6_addr_copy(dest->next_hop_addr, dest->destination_addr); #ifdef LWIP_HOOK_ND6_GET_GW } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { /* Next hop for destination provided by hook function. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); + dest->pmtu = netif->mtu; + ip6_addr_set(&dest->next_hop_addr, next_hop_addr); #endif /* LWIP_HOOK_ND6_GET_GW */ } else { /* We need to select a router. */ i = nd6_select_router(ip6addr, netif); if (i < 0) { /* No router found. */ - ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + ip6_addr_set_any(&dest->destination_addr); return ERR_RTE; } - destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif); /* Start with netif mtu, correct through ICMPv6 if necessary */ - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + dest->pmtu = netif_mtu6(netif); /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(dest->next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); } } - } - #if LWIP_NETIF_HWADDRHINT - if (netif->hints != NULL) { - /* per-pcb cached entry was given */ - netif->hints->addr_hint = nd6_cached_destination_index; - } + if (netif->hints != NULL) { + /* per-pcb cached entry was given */ + netif->hints->addr_hint = nd6_cached_destination_index; + } #endif /* LWIP_NETIF_HWADDRHINT */ + } /* Look in neighbor cache for the next-hop address. */ - if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), - &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + if (ip6_addr_eq(&dest->next_hop_addr, + &(neighbor_cache[dest->cached_neighbor_idx].next_hop_address))) { /* Cache hit. */ /* Do nothing. */ ND6_STATS_INC(nd6.cachehit); } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + i = nd6_find_neighbor_cache_entry(&dest->next_hop_addr); if (i >= 0) { /* Found a matching record, make it new cached entry. */ - nd6_cached_neighbor_index = i; + dest->cached_neighbor_idx = i; } else { /* Neighbor not in cache. Make a new entry. */ i = nd6_new_neighbor_cache_entry(); if (i >= 0) { /* got new neighbor entry. make it our new cached index. */ - nd6_cached_neighbor_index = i; + dest->cached_neighbor_idx = i; } else { /* Could not create a neighbor cache entry. */ return ERR_MEM; } /* Initialize fields. */ - ip6_addr_copy(neighbor_cache[i].next_hop_address, - destination_cache[nd6_cached_destination_index].next_hop_addr); + ip6_addr_copy(neighbor_cache[i].next_hop_address, dest->next_hop_addr); neighbor_cache[i].isrouter = 0; neighbor_cache[i].netif = netif; neighbor_cache[i].state = ND6_INCOMPLETE; @@ -2047,9 +2066,9 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) } /* Reset this destination's age. */ - destination_cache[nd6_cached_destination_index].age = 0; + dest->age = 0; - return nd6_cached_neighbor_index; + return dest->cached_neighbor_idx; } /** @@ -2109,7 +2128,11 @@ nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) /* queue packet ... */ #if LWIP_ND6_QUEUEING /* allocate a new nd6 queue entry */ - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + new_entry = NULL; + if (nd6_queue_size < MEMP_NUM_ND6_QUEUE) { + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + nd6_queue_size++; + } if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { /* Free oldest packet (as per RFC recommendation) */ r = neighbor_cache[neighbor_index].q; @@ -2117,6 +2140,7 @@ nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) r->next = NULL; nd6_free_q(r); new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + nd6_queue_size++; } if (new_entry != NULL) { new_entry->next = NULL; @@ -2175,6 +2199,7 @@ nd6_free_q(struct nd6_q_entry *q) LWIP_ASSERT("r->p != NULL", (r->p != NULL)); pbuf_free(r->p); memp_free(MEMP_ND6_QUEUE, r); + nd6_queue_size--; } } #endif /* LWIP_ND6_QUEUEING */ @@ -2215,6 +2240,7 @@ nd6_send_q(s8_t i) pbuf_free(q->p); /* now queue entry can be freed */ memp_free(MEMP_ND6_QUEUE, q); + nd6_queue_size--; } #else /* LWIP_ND6_QUEUEING */ if (neighbor_cache[i].q != NULL) { @@ -2331,9 +2357,10 @@ nd6_reachability_hint(const ip6_addr_t *ip6addr) { s8_t i; s16_t dst_idx; + struct nd6_destination_cache_entry *dest; /* Find destination in cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + if (ip6_addr_eq(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { dst_idx = nd6_cached_destination_index; ND6_STATS_INC(nd6.cachehit); } else { @@ -2344,11 +2371,12 @@ nd6_reachability_hint(const ip6_addr_t *ip6addr) } /* Find next hop neighbor in cache. */ - if (ip6_addr_cmp(&(destination_cache[dst_idx].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - i = nd6_cached_neighbor_index; + dest = &destination_cache[dst_idx]; + if (ip6_addr_eq(&dest->next_hop_addr, &(neighbor_cache[dest->cached_neighbor_idx].next_hop_address))) { + i = dest->cached_neighbor_idx; ND6_STATS_INC(nd6.cachehit); } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[dst_idx].next_hop_addr)); + i = nd6_find_neighbor_cache_entry(&dest->next_hop_addr); } if (i < 0) { return; diff --git a/src/core/mem.c b/src/core/mem.c index 315fb3c..0aa34a2 100644 --- a/src/core/mem.c +++ b/src/core/mem.c @@ -60,6 +60,7 @@ #include "lwip/stats.h" #include "lwip/err.h" +#include /* snprintf */ #include #if MEM_LIBC_MALLOC @@ -151,7 +152,7 @@ mem_overflow_init_raw(void *p, size_t size) } #endif /* MEM_OVERFLOW_CHECK || MEMP_OVERFLOW_CHECK */ -#if MEM_LIBC_MALLOC || MEM_USE_POOLS +#if MEM_CUSTOM_ALLOCATOR || MEM_USE_POOLS /** mem_init is not used when using pools instead of a heap or using * C library malloc(). @@ -171,23 +172,9 @@ mem_trim(void *mem, mem_size_t size) LWIP_UNUSED_ARG(size); return mem; } -#endif /* MEM_LIBC_MALLOC || MEM_USE_POOLS */ +#endif /* MEM_CUSTOM_ALLOCATOR || MEM_USE_POOLS */ -#if MEM_LIBC_MALLOC -/* lwIP heap implemented using C library malloc() */ - -/* in case C library malloc() needs extra protection, - * allow these defines to be overridden. - */ -#ifndef mem_clib_free -#define mem_clib_free free -#endif -#ifndef mem_clib_malloc -#define mem_clib_malloc malloc -#endif -#ifndef mem_clib_calloc -#define mem_clib_calloc calloc -#endif +#if MEM_CUSTOM_ALLOCATOR #if LWIP_STATS && MEM_STATS #define MEM_LIBC_STATSHELPER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(mem_size_t)) @@ -206,7 +193,7 @@ mem_trim(void *mem, mem_size_t size) void * mem_malloc(mem_size_t size) { - void *ret = mem_clib_malloc(size + MEM_LIBC_STATSHELPER_SIZE); + void *ret = MEM_CUSTOM_MALLOC(size + MEM_LIBC_STATSHELPER_SIZE); if (ret == NULL) { MEM_STATS_INC_LOCKED(err); } else { @@ -233,7 +220,7 @@ mem_free(void *rmem) rmem = (u8_t *)rmem - MEM_LIBC_STATSHELPER_SIZE; MEM_STATS_DEC_USED_LOCKED(used, *(mem_size_t *)rmem); #endif - mem_clib_free(rmem); + MEM_CUSTOM_FREE(rmem); } #elif MEM_USE_POOLS @@ -688,7 +675,7 @@ mem_free(void *rmem) /** * Shrink memory returned by mem_malloc(). * - * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param rmem pointer to memory allocated by mem_malloc the is to be shrunk * @param new_size required size after shrinking (needs to be smaller than or * equal to the previous size) * @return for compatibility reasons: is always == rmem, at the moment @@ -757,7 +744,7 @@ mem_trim(void *rmem, mem_size_t new_size) LWIP_ASSERT("invalid next ptr", mem->next != MEM_SIZE_ALIGNED); /* remember the old next pointer */ next = mem2->next; - /* create new struct mem which is moved directly after the shrinked mem */ + /* create new struct mem which is moved directly after the shrunk mem */ ptr2 = (mem_size_t)(ptr + SIZEOF_STRUCT_MEM + newsize); if (lfree == mem2) { lfree = ptr_to_mem(ptr2); @@ -805,7 +792,7 @@ mem_trim(void *rmem, mem_size_t new_size) /* else { next struct mem is used but size between mem and mem2 is not big enough to create another struct mem - -> don't do anyhting. + -> don't do anything. -> the remaining space stays unused since it is too small } */ #if MEM_OVERFLOW_CHECK @@ -977,14 +964,14 @@ mem_malloc(mem_size_t size_in) #endif /* MEM_USE_POOLS */ -#if MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) +#if MEM_CUSTOM_ALLOCATOR && (!LWIP_STATS || !MEM_STATS) void * mem_calloc(mem_size_t count, mem_size_t size) { - return mem_clib_calloc(count, size); + return MEM_CUSTOM_CALLOC(count, size); } -#else /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ +#else /* MEM_CUSTOM_ALLOCATOR && (!LWIP_STATS || !MEM_STATS) */ /** * Contiguously allocates enough space for count objects that are size bytes * of memory each and returns a pointer to the allocated memory. @@ -1014,4 +1001,4 @@ mem_calloc(mem_size_t count, mem_size_t size) } return p; } -#endif /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ +#endif /* MEM_CUSTOM_ALLOCATOR && (!LWIP_STATS || !MEM_STATS) */ diff --git a/src/core/netif.c b/src/core/netif.c index 088b50e..98e0553 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -80,6 +80,9 @@ #if LWIP_DHCP #include "lwip/dhcp.h" #endif /* LWIP_DHCP */ +#if LWIP_ACD +#include "lwip/acd.h" +#endif /* LWIP_ACD */ #if LWIP_IPV6_DHCP6 #include "lwip/dhcp6.h" #endif /* LWIP_IPV6_DHCP6 */ @@ -140,6 +143,14 @@ static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const i static struct netif loop_netif; +#if LWIP_TESTMODE +struct netif* netif_get_loopif(void) +{ + return &loop_netif; +} +#endif + + /** * Initialize a lwip network interface structure for a loopback interface * @@ -256,16 +267,16 @@ netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_inp * @param state opaque data passed to the new netif * @param init callback function that initializes the interface * @param input callback function that is called to pass - * ingress packets up in the protocol layer stack.\n + * ingress packets up in the protocol layer stack.
* It is recommended to use a function that passes the input directly * to the stack (netif_input(), NO_SYS=1 mode) or via sending a - * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n + * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).
* These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET * to decide whether to forward to ethernet_input() or ip_input(). * In other words, the functions only work when the netif - * driver is implemented correctly!\n + * driver is implemented correctly!
* Most members of struct netif should be be initialized by the - * netif init function = netif driver (init parameter of this function).\n + * netif init function = netif driver (init parameter of this function).
* IPv6: Don't forget to call netif_create_ip6_linklocal_address() after * setting the MAC address in struct netif.hwaddr * (IPv6 requires a link-local address). @@ -331,8 +342,8 @@ netif_add(struct netif *netif, #endif /* LWIP_NUM_NETIF_CLIENT_DATA */ #if LWIP_IPV6 #if LWIP_IPV6_AUTOCONFIG - /* IPv6 address autoconfiguration not enabled by default */ - netif->ip6_autoconfig_enabled = 0; + /* IPv6 address autoconfiguration should be enabled by default */ + netif->ip6_autoconfig_enabled = 1; #endif /* LWIP_IPV6_AUTOCONFIG */ nd6_restart_netif(netif); #endif /* LWIP_IPV6 */ @@ -354,6 +365,9 @@ netif_add(struct netif *netif, netif->num = netif_num; netif->input = input; +#if LWIP_ACD + netif->acd_list = NULL; +#endif /* LWIP_ACD */ NETIF_RESET_HINTS(netif); #if ENABLE_LOOPBACK netif->loop_first = NULL; @@ -463,7 +477,7 @@ netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *ol LWIP_ASSERT("invalid pointer", old_addr != NULL); /* address is actually being changed? */ - if (ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) { + if (ip4_addr_eq(ipaddr, netif_ip4_addr(netif)) == 0) { ip_addr_t new_addr; *ip_2_ip4(&new_addr) = *ipaddr; IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); @@ -473,6 +487,10 @@ netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *ol LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); netif_do_ip_addr_changed(old_addr, &new_addr); +#if LWIP_ACD + acd_netif_ip_addr_changed(netif, old_addr, &new_addr); +#endif /* LWIP_ACD */ + mib2_remove_ip4(netif); mib2_remove_route_ip4(0, netif); /* set new IP address to netif */ @@ -526,7 +544,7 @@ static int netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm) { /* address is actually being changed? */ - if (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0) { + if (ip4_addr_eq(netmask, netif_ip4_netmask(netif)) == 0) { #if LWIP_NETIF_EXT_STATUS_CALLBACK LWIP_ASSERT("invalid pointer", old_nm != NULL); ip_addr_copy(*old_nm, *netif_ip_netmask4(netif)); @@ -590,7 +608,7 @@ static int netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) { /* address is actually being changed? */ - if (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) { + if (ip4_addr_eq(gw, netif_ip4_gw(netif)) == 0) { #if LWIP_NETIF_EXT_STATUS_CALLBACK LWIP_ASSERT("invalid pointer", old_gw != NULL); ip_addr_copy(*old_gw, *netif_ip_gw4(netif)); @@ -724,6 +742,12 @@ netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t * #if LWIP_NETIF_EXT_STATUS_CALLBACK if (change_reason != LWIP_NSC_NONE) { change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED; + } + if (!remove) { + /* Issue a callback even if the address hasn't changed, eg. DHCP reboot */ + change_reason |= LWIP_NSC_IPV4_ADDR_VALID; + } + if (change_reason != LWIP_NSC_NONE) { netif_invoke_ext_callback(netif, change_reason, &cb_args); } #endif @@ -888,8 +912,11 @@ netif_issue_reports(struct netif *netif, u8_t report_type) #if LWIP_IPV4 if ((report_type & NETIF_REPORT_TYPE_IPV4) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { -#if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ +#if LWIP_ARP && !LWIP_ACD + /* For Ethernet network interfaces: + * we would like to send a "gratuitous ARP". + * Only needs to be done here if ACD isn't configured. + */ if (netif->flags & (NETIF_FLAG_ETHARP)) { etharp_gratuitous(netif); } @@ -998,11 +1025,11 @@ netif_set_link_up(struct netif *netif) netif_set_flags(netif, NETIF_FLAG_LINK_UP); #if LWIP_DHCP - dhcp_network_changed(netif); + dhcp_network_changed_link_up(netif); #endif /* LWIP_DHCP */ #if LWIP_AUTOIP - autoip_network_changed(netif); + autoip_network_changed_link_up(netif); #endif /* LWIP_AUTOIP */ netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); @@ -1034,6 +1061,15 @@ netif_set_link_down(struct netif *netif) if (netif->flags & NETIF_FLAG_LINK_UP) { netif_clear_flags(netif, NETIF_FLAG_LINK_UP); + +#if LWIP_AUTOIP + autoip_network_changed_link_down(netif); +#endif /* LWIP_AUTOIP */ + +#if LWIP_ACD + acd_network_changed_link_down(netif); +#endif /* LWIP_ACD */ + #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES netif->mtu6 = netif->mtu; #endif @@ -1373,7 +1409,7 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); } - /* @todo: remove/readd mib2 ip6 entries? */ + /* @todo: remove/re-add mib2 ip6 entries? */ ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr); @@ -1496,7 +1532,7 @@ netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) { + ip6_addr_zoneless_eq(netif_ip6_addr(netif, i), ip6addr)) { return i; } } @@ -1552,7 +1588,7 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) /* Set a link-local zone. Even though the zone is implied by the owning * netif, setting the zone anyway has two important conceptual advantages: * 1) it avoids the need for a ton of exceptions in internal code, allowing - * e.g. ip6_addr_cmp() to be used on local addresses; + * e.g. ip6_addr_eq() to be used on local addresses; * 2) the properly zoned address is visible externally, e.g. when any outside * code enumerates available addresses or uses one to bind a socket. * Any external code unaware of address scoping is likely to just ignore the @@ -1789,11 +1825,11 @@ netif_remove_ext_callback(netif_ext_callback_t* callback) if (iter == callback) { LWIP_ASSERT("last != NULL", last != NULL); last->next = callback->next; - callback->next = NULL; - return; + break; } } } + callback->next = NULL; } /** @@ -1810,8 +1846,10 @@ netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const LWIP_ASSERT("netif must be != NULL", netif != NULL); while (callback != NULL) { + /* cache next pointer: the callback might unregister itself */ + netif_ext_callback_t *next = callback->next; callback->callback_fn(netif, reason, args); - callback = callback->next; + callback = next; } } #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 7638dfd..54a6e0e 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -186,6 +186,8 @@ pbuf_init_alloced_pbuf(struct pbuf *p, void *payload, u16_t tot_len, u16_t len, p->flags = flags; p->ref = 1; p->if_idx = NETIF_NO_INDEX; + + LWIP_PBUF_CUSTOM_DATA_INIT(p); } /** @@ -441,8 +443,11 @@ pbuf_realloc(struct pbuf *p, u16_t new_len) #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ ) { /* reallocate and adjust the length of the pbuf that will be split */ - q = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len)); - LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + struct pbuf *r = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len)); + LWIP_ASSERT("mem_trim returned r == NULL", r != NULL); + /* help to detect faulty overridden implementation of mem_trim */ + LWIP_ASSERT("mem_trim returned r != q", r == q); + LWIP_UNUSED_ARG(r); } /* adjust length fields for new last pbuf */ q->len = rem_len; @@ -677,7 +682,7 @@ pbuf_free_header(struct pbuf *q, u16_t size) struct pbuf *f = p; free_left = (u16_t)(free_left - p->len); p = p->next; - f->next = 0; + f->next = NULL; pbuf_free(f); } else { pbuf_remove_header(p, free_left); @@ -705,7 +710,6 @@ pbuf_free_header(struct pbuf *q, u16_t size) * @return the number of pbufs that were de-allocated * from the head of the chain. * - * @note MUST NOT be called on a packet queue (Not verified to work yet). * @note the reference counter of a pbuf equals the number of pointers * that refer to the pbuf (or into the pbuf). * @@ -856,6 +860,7 @@ pbuf_cat(struct pbuf *h, struct pbuf *t) LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", ((h != NULL) && (t != NULL)), return;); + LWIP_ASSERT("Creating an infinite loop", h != t); /* proceed to last pbuf of chain */ for (p = h; p->next != NULL; p = p->next) { @@ -941,12 +946,7 @@ pbuf_dechain(struct pbuf *p) /** * @ingroup pbuf - * Create PBUF_RAM copies of pbufs. - * - * Used to queue packets on behalf of the lwIP stack, such as - * ARP based queueing. - * - * @note You MUST explicitly use p = pbuf_take(p); + * Copy the contents of one packet buffer into another. * * @note Only one packet is copied, no packet queue! * @@ -956,6 +956,7 @@ pbuf_dechain(struct pbuf *p) * @return ERR_OK if pbuf was copied * ERR_ARG if one of the pbufs is NULL or p_to is not big * enough to hold p_from + * ERR_VAL if any of the pbufs are part of a queue */ err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) @@ -987,8 +988,7 @@ pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset) { - size_t offset_to = offset, offset_from = 0, len_calc; - u16_t len; + size_t offset_to = offset, offset_from = 0, len; LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n", (const void *)p_to, (const void *)p_from, copy_len, offset)); @@ -1005,16 +1005,16 @@ pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_ /* copy one part of the original chain */ if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { /* complete current p_from fits into current p_to */ - len_calc = p_from->len - offset_from; + len = p_from->len - offset_from; } else { /* current p_from does not fit into current p_to */ - len_calc = p_to->len - offset_to; + len = p_to->len - offset_to; } - len = (u16_t)LWIP_MIN(copy_len, len_calc); + len = LWIP_MIN(copy_len, len); MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len); offset_to += len; offset_from += len; - copy_len -= len; + copy_len = (u16_t)(copy_len - len); LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); if (offset_from >= p_from->len) { @@ -1097,12 +1097,15 @@ pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset * a copy into the user-supplied buffer. * * @param p the pbuf from which to copy data - * @param buffer the application supplied buffer - * @param bufsize size of the application supplied buffer - * @param len length of data to copy (dataptr must be big enough). No more - * than buf->tot_len will be copied, irrespective of len + * @param buffer the application supplied buffer. May be NULL if the caller does not + * want to copy. In this case, offset + len should be checked against p->tot_len, + * since there's no way for the caller to know why NULL is returned. + * @param bufsize size of the application supplied buffer (when buffer is != NULL) + * @param len length of data to copy (p and buffer must be big enough) * @param offset offset into the packet buffer from where to begin copying len bytes - * @return the number of bytes copied, or 0 on failure + * @return - pointer into pbuf payload if that is already contiguous (no copy needed) + * - pointer to 'buffer' if data was not contiguous and had to be copied + * - NULL on error */ void * pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset) @@ -1111,8 +1114,7 @@ pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t le u16_t out_offset; LWIP_ERROR("pbuf_get_contiguous: invalid buf", (p != NULL), return NULL;); - LWIP_ERROR("pbuf_get_contiguous: invalid dataptr", (buffer != NULL), return NULL;); - LWIP_ERROR("pbuf_get_contiguous: invalid dataptr", (bufsize >= len), return NULL;); + LWIP_ERROR("pbuf_get_contiguous: invalid bufsize", (buffer == NULL) || (bufsize >= len), return NULL;); q = pbuf_skip_const(p, offset, &out_offset); if (q != NULL) { @@ -1120,6 +1122,10 @@ pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t le /* all data in this pbuf, return zero-copy */ return (u8_t *)q->payload + out_offset; } + if (buffer == NULL) { + /* the caller does not want to copy */ + return NULL; + } /* need to copy */ if (pbuf_copy_partial(q, buffer, len, out_offset) != len) { /* copying failed: pbuf is too short */ @@ -1206,7 +1212,7 @@ pbuf_skip_const(const struct pbuf *in, u16_t in_offset, u16_t *out_offset) * @param in input pbuf * @param in_offset offset to skip * @param out_offset resulting offset in the returned pbuf - * @return the pbuf in the queue where the offset is + * @return the pbuf in the queue where the offset is or NULL when the offset is too high */ struct pbuf * pbuf_skip(struct pbuf *in, u16_t in_offset, u16_t *out_offset) diff --git a/src/core/raw.c b/src/core/raw.c index 3b34544..d85aaec 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -2,14 +2,14 @@ * @file * Implementation of raw protocol PCBs for low-level handling of * different types of protocols besides (or overriding) those - * already available in lwIP.\n + * already available in lwIP.
* See also @ref raw_raw * * @defgroup raw_raw RAW * @ingroup callbackstyle_api * Implementation of raw protocol PCBs for low-level handling of * different types of protocols besides (or overriding) those - * already available in lwIP.\n + * already available in lwIP.
* @see @ref api */ @@ -106,7 +106,7 @@ raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) #endif /* LWIP_IPV4 */ /* Handle IPv4 and IPv6: catch all or exact match */ if (ip_addr_isany(&pcb->local_ip) || - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + ip_addr_eq(&pcb->local_ip, ip_current_dest_addr())) { return 1; } } @@ -166,7 +166,7 @@ raw_input(struct pbuf *p, struct netif *inp) while (pcb != NULL) { if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) || - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + ip_addr_eq(&pcb->remote_ip, ip_current_src_addr()))) { /* receive callback function available? */ if (pcb->recv != NULL) { u8_t eaten; @@ -384,6 +384,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) if (netif == NULL) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("\n")); return ERR_RTE; } @@ -609,6 +610,7 @@ raw_new(u8_t proto) #if LWIP_MULTICAST_TX_OPTIONS raw_set_multicast_ttl(pcb, RAW_TTL); #endif /* LWIP_MULTICAST_TX_OPTIONS */ + pcb_tci_init(pcb); pcb->next = raw_pcbs; raw_pcbs = pcb; } @@ -659,7 +661,7 @@ void raw_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_a if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { + if (ip_addr_eq(&rpcb->local_ip, old_addr)) { /* The PCB is bound to the old ipaddr and * is set to bound to the new one instead */ ip_addr_copy(rpcb->local_ip, *new_addr); diff --git a/src/core/stats.c b/src/core/stats.c index 34e9b27..95445ec 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -166,4 +166,3 @@ stats_display(void) #endif /* LWIP_STATS_DISPLAY */ #endif /* LWIP_STATS */ - diff --git a/src/core/sys.c b/src/core/sys.c index 5f08352..69d7197 100644 --- a/src/core/sys.c +++ b/src/core/sys.c @@ -45,30 +45,30 @@ * No need to implement functions in this section in NO_SYS mode. * The OS-specific code should be implemented in arch/sys_arch.h * and sys_arch.c of your port. - * + * * 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. - * + * * 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). - * + * * Note: * ----- * Be careful with using mem_malloc() in sys_arch. When malloc() refers to @@ -96,7 +96,7 @@ * 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. + * in a mailbox is just a pointer, nothing more. * * @defgroup sys_time Time * @ingroup sys_layer diff --git a/src/core/tcp.c b/src/core/tcp.c index 371db2b..ea95ffe 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -5,13 +5,13 @@ * * @defgroup tcp_raw TCP * @ingroup callbackstyle_api - * Transmission Control Protocol for IP\n + * Transmission Control Protocol for IP
* @see @ref api * * Common functions for the TCP implementation, such as functions * for manipulating the data structures and the TCP timer functions. TCP functions - * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n - * + * related to input and output is found in tcp_in.c and tcp_out.c respectively.
+ * * TCP connection setup * -------------------- * The functions used for setting up connections is similar to that of @@ -24,7 +24,7 @@ * - tcp_listen() and tcp_listen_with_backlog() * - tcp_accept() * - tcp_connect() - * + * * Sending TCP data * ---------------- * TCP data is sent by enqueueing the data with a call to tcp_write() and @@ -34,7 +34,7 @@ * - tcp_write() * - tcp_output() * - tcp_sent() - * + * * Receiving TCP data * ------------------ * TCP data reception is callback based - an application specified @@ -44,7 +44,7 @@ * window. * - tcp_recv() * - tcp_recved() - * + * * Application polling * ------------------- * When a connection is idle (i.e., no data is either transmitted or @@ -62,7 +62,7 @@ * - tcp_close() * - tcp_abort() * - tcp_err() - * + * */ /* @@ -469,7 +469,7 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb) * a closing state), the connection is closed, and put in a closing state. * The pcb is then automatically freed in tcp_slowtmr(). It is therefore * unsafe to reference it (unless an error is returned). - * + * * 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 @@ -502,7 +502,7 @@ tcp_close(struct tcp_pcb *pcb) * @ingroup tcp_raw * Causes all or part of a full-duplex connection of this PCB to be shut down. * This doesn't deallocate the PCB unless shutting down both sides! - * Shutting down both sides is the same as calling tcp_close, so if it succeds + * Shutting down both sides is the same as calling tcp_close, so if it succeeds * (i.e. returns ER_OK), the PCB must not be referenced any more! * * @param pcb PCB to shutdown @@ -728,7 +728,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && (ip_addr_isany(&cpcb->local_ip) || ip_addr_isany(ipaddr) || - ip_addr_cmp(&cpcb->local_ip, ipaddr))) { + ip_addr_eq(&cpcb->local_ip, ipaddr))) { return ERR_USE; } } @@ -798,7 +798,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) * When an incoming connection is accepted, the function specified with * the tcp_accept() function will be called. The pcb has 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 @@ -813,7 +813,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) * The backlog 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. - * + * * @param pcb the original tcp_pcb * @param backlog the incoming connections queue limit * @return tcp_pcb used for listening, consumes less memory. @@ -871,7 +871,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) this port is only used once for every local IP. */ for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { if ((lpcb->local_port == pcb->local_port) && - ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + ip_addr_eq(&lpcb->local_ip, &pcb->local_ip)) { /* this address/port is already used */ lpcb = NULL; res = ERR_USE; @@ -893,6 +893,9 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) lpcb->netif_idx = pcb->netif_idx; lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; +#if LWIP_VLAN_PCP + lpcb->netif_hints.tci = pcb->netif_hints.tci; +#endif /* LWIP_VLAN_PCP */ #if LWIP_IPV4 && LWIP_IPV6 IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); #endif /* LWIP_IPV4 && LWIP_IPV6 */ @@ -1040,7 +1043,7 @@ tcp_new_port(void) * Connects to another host. The function given as the "connected" * argument will be called when the connection has been established. * Sets up the pcb to connect to the remote host and sends the - * initial SYN segment which opens the connection. + * 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 @@ -1059,7 +1062,7 @@ tcp_new_port(void) * @param ipaddr the remote ip address to connect to * @param port the remote tcp port to connect to * @param connected callback function to call when connected (on error, - the err calback will be called) + the err callback will be called) * @return ERR_VAL if invalid arguments are given * ERR_OK if connect request has been sent * other err_t values if connect request couldn't be sent @@ -1131,8 +1134,8 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { if ((cpcb->local_port == pcb->local_port) && (cpcb->remote_port == port) && - ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && - ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + ip_addr_eq(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_eq(&cpcb->remote_ip, ipaddr)) { /* linux returns EISCONN here, but ERR_USE should be OK for us */ return ERR_USE; } @@ -1212,9 +1215,9 @@ tcp_slowtmr(void) } while (pcb != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); if (pcb->last_timer == tcp_timer_ctr) { /* skip this pcb, we have already processed it */ prev = pcb; @@ -1712,14 +1715,14 @@ tcp_kill_prio(u8_t prio) mprio = LWIP_MIN(TCP_PRIO_MAX, prio); - /* We want to kill connections with a lower prio, so bail out if + /* We want to kill connections with a lower prio, so bail out if * supplied prio is 0 - there can never be a lower prio */ if (mprio == 0) { return; } - /* We only want kill connections with a lower prio, so decrement prio by one + /* We only want kill connections with a lower prio, so decrement prio by one * and start searching for oldest connection with same or lower priority than mprio. * We want to find the connections with the lowest possible prio, and among * these the one with the longest inactivity time. @@ -1898,14 +1901,16 @@ tcp_alloc(u8_t prio) /* As initial send MSS, we use TCP_MSS but limit it to 536. The send MSS is updated when an MSS option is received. */ pcb->mss = INITIAL_MSS; - pcb->rto = 3000 / TCP_SLOW_INTERVAL; - pcb->sv = 3000 / TCP_SLOW_INTERVAL; + /* Set initial TCP's retransmission timeout to 3000 ms by default. + This value could be configured in lwipopts */ + pcb->rto = LWIP_TCP_RTO_TIME / TCP_SLOW_INTERVAL; + pcb->sv = LWIP_TCP_RTO_TIME / TCP_SLOW_INTERVAL; pcb->rtime = -1; pcb->cwnd = 1; pcb->tmr = tcp_ticks; pcb->last_timer = tcp_timer_ctr; - /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example + /* RFC 5681 recommends setting ssthresh arbitrarily high and gives an example of using the largest advertised receive window. We've seen complications with receiving TCPs that use window scaling and/or window auto-tuning where the initial advertised window is very small and then grows rapidly once the @@ -1924,6 +1929,7 @@ tcp_alloc(u8_t prio) pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; #endif /* LWIP_TCP_KEEPALIVE */ + pcb_tci_init(pcb); } return pcb; } @@ -2044,7 +2050,7 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) * @ingroup tcp_raw * Used to specify the function that should be called when a fatal error * has occurred on the connection. - * + * * 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 @@ -2095,7 +2101,7 @@ tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) * 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. - * + * * 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 @@ -2309,7 +2315,7 @@ tcp_netif_ip_addr_changed_pcblist(const ip_addr_t *old_addr, struct tcp_pcb *pcb while (pcb != NULL) { /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&pcb->local_ip, old_addr) + if (ip_addr_eq(&pcb->local_ip, old_addr) #if LWIP_AUTOIP /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) @@ -2344,7 +2350,7 @@ tcp_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr) /* PCB bound to current local interface address? */ for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { + if (ip_addr_eq(&lpcb->local_ip, old_addr)) { /* The PCB is listening to the old ipaddr and * is set to listen to the new one instead */ ip_addr_copy(lpcb->local_ip, *new_addr); @@ -2537,7 +2543,7 @@ tcp_pcbs_sane(void) /** * @defgroup tcp_raw_extargs ext arguments * @ingroup tcp_raw - * Additional data storage per tcp pcb\n + * Additional data storage per tcp pcb
* @see @ref tcp_raw * * When LWIP_TCP_PCB_NUM_EXT_ARGS is > 0, every tcp pcb (including listen pcb) @@ -2595,7 +2601,7 @@ tcp_ext_arg_alloc_id(void) * @param callbacks callback table (const since it is referenced, not copied!) */ void -tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks) +tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, u8_t id, const struct tcp_ext_arg_callbacks * const callbacks) { LWIP_ASSERT("pcb != NULL", pcb != NULL); LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS); @@ -2614,7 +2620,7 @@ tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_ * @param id ext_args index to set (allocated via @ref tcp_ext_arg_alloc_id) * @param arg data pointer to set */ -void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg) +void tcp_ext_arg_set(struct tcp_pcb *pcb, u8_t id, void *arg) { LWIP_ASSERT("pcb != NULL", pcb != NULL); LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS); @@ -2632,7 +2638,7 @@ void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg) * @param id ext_args index to set (allocated via @ref tcp_ext_arg_alloc_id) * @return data pointer at the given index */ -void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id) +void *tcp_ext_arg_get(const struct tcp_pcb *pcb, u8_t id) { LWIP_ASSERT("pcb != NULL", pcb != NULL); LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS); diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 2202e38..1b17e40 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -261,8 +261,8 @@ tcp_input(struct pbuf *p, struct netif *inp) if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + ip_addr_eq(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_eq(&pcb->local_ip, ip_current_dest_addr())) { /* Move this PCB to the front of the list so that subsequent lookups will be faster (we exploit locality in TCP segment arrivals). */ @@ -294,8 +294,8 @@ tcp_input(struct pbuf *p, struct netif *inp) if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + ip_addr_eq(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_eq(&pcb->local_ip, ip_current_dest_addr())) { /* We don't really care enough to move this PCB to the front of the list since we are not very likely to receive that many segments for connections in TIME-WAIT. */ @@ -333,7 +333,7 @@ tcp_input(struct pbuf *p, struct netif *inp) break; #endif /* SO_REUSE */ } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { - if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { + if (ip_addr_eq(&lpcb->local_ip, ip_current_dest_addr())) { /* found an exact match */ break; } else if (ip_addr_isany(&lpcb->local_ip)) { @@ -576,7 +576,7 @@ tcp_input(struct pbuf *p, struct netif *inp) if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { TCP_STATS_INC(tcp.proterr); TCP_STATS_INC(tcp.drop); - tcp_rst(NULL, ackno, seqno + tcplen, ip_current_dest_addr(), + tcp_rst_netif(ip_data.current_input_netif, ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), tcphdr->dest, tcphdr->src); } pbuf_free(p); @@ -592,7 +592,7 @@ tcp_input(struct pbuf *p, struct netif *inp) } /** Called from tcp_input to check for TF_CLOSED flag. This results in closing - * and deallocating a pcb at the correct place to ensure noone references it + * and deallocating a pcb at the correct place to ensure no one references it * any more. * @returns 1 if the pcb has been closed and deallocated, 0 otherwise */ @@ -646,7 +646,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) /* For incoming segments with the ACK flag set, respond with a RST. */ LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); - tcp_rst((const struct tcp_pcb *)pcb, ackno, seqno + tcplen, ip_current_dest_addr(), + tcp_rst_netif(ip_data.current_input_netif, ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), tcphdr->dest, tcphdr->src); } else if (flags & TCP_SYN) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); @@ -690,6 +690,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG npcb->listener = pcb; #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ +#if LWIP_VLAN_PCP + npcb->netif_hints.tci = pcb->netif_hints.tci; +#endif /* LWIP_VLAN_PCP */ /* inherit socket options */ npcb->so_options = pcb->so_options & SOF_INHERITED; npcb->netif_idx = pcb->netif_idx; @@ -849,6 +852,13 @@ tcp_process(struct tcp_pcb *pcb) tcp_parseopt(pcb); + if (flags & TCP_SYN) { + /* accept SYN only in 2 states: */ + if ((pcb->state != SYN_SENT) && (pcb->state != SYN_RCVD)) { + return ERR_OK; + } + } + /* Do different things depending on the TCP state. */ switch (pcb->state) { case SYN_SENT: @@ -921,7 +931,12 @@ tcp_process(struct tcp_pcb *pcb) } break; case SYN_RCVD: - if (flags & TCP_ACK) { + if (flags & TCP_SYN) { + if (seqno == pcb->rcv_nxt - 1) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + } else if (flags & TCP_ACK) { /* expected ACK number? */ if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) { pcb->state = ESTABLISHED; @@ -972,9 +987,6 @@ tcp_process(struct tcp_pcb *pcb) tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), tcphdr->dest, tcphdr->src); } - } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { - /* Looks like another copy of the SYN - retransmit our SYN-ACK */ - tcp_rexmit(pcb); } break; case CLOSE_WAIT: @@ -1143,7 +1155,6 @@ tcp_receive(struct tcp_pcb *pcb) { s16_t m; u32_t right_wnd_edge; - int found_dupack = 0; LWIP_ASSERT("tcp_receive: invalid pcb", pcb != NULL); LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); @@ -1205,7 +1216,6 @@ tcp_receive(struct tcp_pcb *pcb) if (pcb->rtime >= 0) { /* Clause 5 */ if (pcb->lastack == ackno) { - found_dupack = 1; if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { ++pcb->dupacks; } @@ -1221,11 +1231,6 @@ tcp_receive(struct tcp_pcb *pcb) } } } - /* If Clause (1) or more is true, but not a duplicate ack, reset - * count of consecutive duplicate acks */ - if (!found_dupack) { - pcb->dupacks = 0; - } } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) { /* We come here when the ACK acknowledges new data. */ tcpwnd_size_t acked; @@ -1481,7 +1486,7 @@ tcp_receive(struct tcp_pcb *pcb) } pbuf_realloc(inseg.p, inseg.len); tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd", (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); } #if TCP_QUEUE_OOSEQ @@ -1530,7 +1535,7 @@ tcp_receive(struct tcp_pcb *pcb) } pbuf_realloc(inseg.p, inseg.len); tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue", (seqno + tcplen) == next->tcphdr->seqno); } pcb->ooseq = next; @@ -1541,7 +1546,7 @@ tcp_receive(struct tcp_pcb *pcb) pcb->rcv_nxt = seqno + tcplen; /* Update the receiver's (our) window. */ - LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd", pcb->rcv_wnd >= tcplen); pcb->rcv_wnd -= tcplen; tcp_update_rcv_ann_wnd(pcb); @@ -1559,7 +1564,7 @@ tcp_receive(struct tcp_pcb *pcb) recv_data = inseg.p; /* Since this pbuf now is the responsibility of the application, we delete our reference to it so that we won't - (mistakingly) deallocate it. */ + (mistakenly) deallocate it. */ inseg.p = NULL; } if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { @@ -1577,7 +1582,7 @@ tcp_receive(struct tcp_pcb *pcb) seqno = pcb->ooseq->tcphdr->seqno; pcb->rcv_nxt += TCP_TCPLEN(cseg); - LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd", pcb->rcv_wnd >= TCP_TCPLEN(cseg)); pcb->rcv_wnd -= TCP_TCPLEN(cseg); @@ -1682,10 +1687,20 @@ tcp_receive(struct tcp_pcb *pcb) ->ooseq. We check the lengths to see which one to discard. */ if (inseg.len > next->len) { + struct tcp_seg* cseg; + + /* If next segment is the last segment in ooseq + and smaller than inseg, that means it has been + trimmed before to fit our window, so we just + break here. */ + if (next->next == NULL) { + break; + } + /* The incoming segment is larger than the old segment. We replace some segments with the new one. */ - struct tcp_seg *cseg = tcp_seg_copy(&inseg); + cseg = tcp_seg_copy(&inseg); if (cseg != NULL) { if (prev != NULL) { prev->next = cseg; @@ -1782,7 +1797,7 @@ tcp_receive(struct tcp_pcb *pcb) next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); pbuf_realloc(next->next->p, next->next->len); tcplen = TCP_TCPLEN(next->next); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd", (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); } } diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 8149d39..cfcc55d 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -106,7 +106,7 @@ #endif /* TCP_CHECKSUM_ON_COPY*/ /** Define this to 1 for an extra check that the output checksum is valid - * (usefule when the checksum is generated by the application, not the stack) */ + * (useful when the checksum is generated by the application, not the stack) */ #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 #endif @@ -126,6 +126,9 @@ /* Forward declarations.*/ static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); +static err_t tcp_output_control_segment_netif(const struct tcp_pcb *pcb, struct pbuf *p, + const ip_addr_t *src, const ip_addr_t *dst, + struct netif *netif); /* tcp_route: common code that returns a fixed bound netif or calls ip_route */ static struct netif * @@ -298,7 +301,7 @@ tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, /** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). * * @param pcb the tcp pcb to check for - * @param len length of data to send (checked agains snd_buf) + * @param len length of data to send (checked against snd_buf) * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise */ static err_t @@ -355,7 +358,7 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len) * it can send them more efficiently by combining them together). * To prompt the system to send data now, call tcp_output() after * calling tcp_write(). - * + * * This function 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 @@ -1037,12 +1040,12 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) u8_t optflags = 0; u8_t optlen = 0; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", (flags & (TCP_SYN | TCP_FIN)) != 0); LWIP_ASSERT("tcp_enqueue_flags: invalid pcb", pcb != NULL); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + /* No need to check pcb->snd_queuelen if only SYN or FIN are allowed! */ /* Get options for this segment. This is a special case since this is the @@ -1922,65 +1925,61 @@ static err_t tcp_output_control_segment(const struct tcp_pcb *pcb, struct pbuf *p, const ip_addr_t *src, const ip_addr_t *dst) { - err_t err; struct netif *netif; LWIP_ASSERT("tcp_output_control_segment: invalid pbuf", p != NULL); netif = tcp_route(pcb, src, dst); if (netif == NULL) { - err = ERR_RTE; - } else { - u8_t ttl, tos; + pbuf_free(p); + return ERR_RTE; + } + return tcp_output_control_segment_netif(pcb, p, src, dst, netif); +} + +/** Output a control segment pbuf to IP. + * + * Called instead of tcp_output_control_segment when we don't have a pcb but we + * do know the interface to send to. + */ +static err_t +tcp_output_control_segment_netif(const struct tcp_pcb *pcb, struct pbuf *p, + const ip_addr_t *src, const ip_addr_t *dst, + struct netif *netif) +{ + err_t err; + u8_t ttl, tos; + + LWIP_ASSERT("tcp_output_control_segment_netif: no netif given", netif != NULL); + #if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - src, dst); - } + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + src, dst); + } #endif - if (pcb != NULL) { - NETIF_SET_HINTS(netif, LWIP_CONST_CAST(struct netif_hint*, &(pcb->netif_hints))); - ttl = pcb->ttl; - tos = pcb->tos; - } else { - /* Send output with hardcoded TTL/HL since we have no access to the pcb */ - ttl = TCP_TTL; - tos = 0; - } - TCP_STATS_INC(tcp.xmit); - err = ip_output_if(p, src, dst, ttl, tos, IP_PROTO_TCP, netif); - NETIF_RESET_HINTS(netif); + if (pcb != NULL) { + NETIF_SET_HINTS(netif, LWIP_CONST_CAST(struct netif_hint*, &(pcb->netif_hints))); + ttl = pcb->ttl; + tos = pcb->tos; + } else { + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ttl = TCP_TTL; + tos = 0; } + TCP_STATS_INC(tcp.xmit); + err = ip_output_if(p, src, dst, ttl, tos, IP_PROTO_TCP, netif); + NETIF_RESET_HINTS(netif); + pbuf_free(p); return err; } -/** - * Send a TCP RESET packet (empty segment with RST flag set) either to - * abort a connection or to show that there is no matching local connection - * for a received segment. - * - * Called by tcp_abort() (to abort a local connection), tcp_input() (if no - * matching local pcb was found), tcp_listen_input() (if incoming segment - * has ACK flag set) and tcp_process() (received segment in the wrong state) - * - * Since a RST segment is in most cases not sent for an active connection, - * tcp_rst() has a number of arguments that are taken from a tcp_pcb for - * most other segment output functions. - * - * @param pcb TCP pcb (may be NULL if no pcb is available) - * @param seqno the sequence number to use for the outgoing segment - * @param ackno the acknowledge number to use for the outgoing segment - * @param local_ip the local IP address to send the segment from - * @param remote_ip the remote IP address to send the segment to - * @param local_port the local TCP port to send the segment from - * @param remote_port the remote TCP port to send the segment to - */ -void -tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, - const ip_addr_t *local_ip, const ip_addr_t *remote_ip, - u16_t local_port, u16_t remote_port) +static struct pbuf * +tcp_rst_common(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) { struct pbuf *p; u16_t wnd; @@ -1988,6 +1987,9 @@ tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, LWIP_ASSERT("tcp_rst: invalid local_ip", local_ip != NULL); LWIP_ASSERT("tcp_rst: invalid remote_ip", remote_ip != NULL); + /* these two are passed only for checks, disable warnings without asserts */ + LWIP_UNUSED_ARG(local_ip); + LWIP_UNUSED_ARG(remote_ip); optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb); @@ -2001,14 +2003,81 @@ tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, remote_port, TCP_RST | TCP_ACK, wnd); if (p == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); - return; + return NULL; } tcp_output_fill_options(pcb, p, 0, 0); MIB2_STATS_INC(mib2.tcpoutrsts); - tcp_output_control_segment(pcb, p, local_ip, remote_ip); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); + return p; +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) to abort a + * connection. + * + * Called by tcp_abort() (to abort a local connection), tcp_closen() (if not + * all data has been received by the application), tcp_timewait_input() (if a + * SYN is received) and tcp_process() (received segment in the wrong state). + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param pcb TCP pcb (may be NULL if no pcb is available) + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + + p = tcp_rst_common(pcb, seqno, ackno, local_ip, remote_ip, local_port, remote_port); + if (p != NULL) { + tcp_output_control_segment(pcb, p, local_ip, remote_ip); + } +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) to show that there + * is no matching local connection for a received segment. + * + * Called by tcp_input() (if no matching local pcb was found) and + * tcp_listen_input() (if incoming segment has ACK flag set). + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param netif the netif on which to send the RST (since we have no pcb) + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst_netif(struct netif *netif, u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + if (netif) { + struct pbuf *p = tcp_rst_common(NULL, seqno, ackno, local_ip, remote_ip, local_port, remote_port); + if (p != NULL) { + tcp_output_control_segment_netif(NULL, p, local_ip, remote_ip, netif); + } + } else { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_rst_netif: no netif given\n")); + } } /** diff --git a/src/core/timeouts.c b/src/core/timeouts.c index f37acfe..91657eb 100644 --- a/src/core/timeouts.c +++ b/src/core/timeouts.c @@ -51,7 +51,7 @@ #include "lwip/ip4_frag.h" #include "lwip/etharp.h" #include "lwip/dhcp.h" -#include "lwip/autoip.h" +#include "lwip/acd.h" #include "lwip/igmp.h" #include "lwip/dns.h" #include "lwip/nd6.h" @@ -91,9 +91,9 @@ const struct lwip_cyclic_timer lwip_cyclic_timers[] = { {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)}, {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)}, #endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, -#endif /* LWIP_AUTOIP */ +#if LWIP_ACD + {ACD_TMR_INTERVAL, HANDLER(acd_tmr)}, +#endif /* LWIP_ACD */ #if LWIP_IGMP {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, #endif /* LWIP_IGMP */ @@ -241,7 +241,7 @@ lwip_cyclic_timer(void *arg) cyclic->handler(); now = sys_now(); - next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */ + next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */ if (TIME_LESS_THAN(next_timeout_time, now)) { /* timer would immediately expire again -> "overload" -> restart without any correction */ #if LWIP_DEBUG_TIMERNAMES @@ -296,7 +296,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) LWIP_ASSERT("Timeout time too long, max is LWIP_UINT32_MAX/4 msecs", msecs <= (LWIP_UINT32_MAX / 4)); - next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */ + next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */ #if LWIP_DEBUG_TIMERNAMES sys_timeout_abs(next_timeout_time, handler, arg, handler_name); diff --git a/src/core/udp.c b/src/core/udp.c index 0b609d3..c787ae0 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -1,12 +1,12 @@ /** * @file - * User Datagram Protocol module\n - * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n + * User Datagram Protocol module
+ * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).
* See also @ref udp_raw * * @defgroup udp_raw UDP * @ingroup callbackstyle_api - * User Datagram Protocol module\n + * User Datagram Protocol module
* @see @ref api */ @@ -163,14 +163,14 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) { if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || - ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { + ip4_addr_net_eq(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { return 1; } } } else #endif /* LWIP_IPV4 */ /* Handle IPv4 and IPv6: all or exact match */ - if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + if (ip_addr_isany(&pcb->local_ip) || ip_addr_eq(&pcb->local_ip, ip_current_dest_addr())) { return 1; } } @@ -268,9 +268,9 @@ udp_input(struct pbuf *p, struct netif *inp) #if LWIP_IPV4 } else if (broadcast && ip4_current_dest_addr()->addr == IPADDR_BROADCAST) { /* global broadcast address (only valid for IPv4; match was checked before) */ - if (!IP_IS_V4_VAL(uncon_pcb->local_ip) || !ip4_addr_cmp(ip_2_ip4(&uncon_pcb->local_ip), netif_ip4_addr(inp))) { + if (!IP_IS_V4_VAL(uncon_pcb->local_ip) || !ip4_addr_eq(ip_2_ip4(&uncon_pcb->local_ip), netif_ip4_addr(inp))) { /* uncon_pcb does not match the input netif, check this pcb */ - if (IP_IS_V4_VAL(pcb->local_ip) && ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), netif_ip4_addr(inp))) { + if (IP_IS_V4_VAL(pcb->local_ip) && ip4_addr_eq(ip_2_ip4(&pcb->local_ip), netif_ip4_addr(inp))) { /* better match */ uncon_pcb = pcb; } @@ -288,7 +288,7 @@ udp_input(struct pbuf *p, struct netif *inp) /* compare PCB remote addr+port to UDP source addr+port */ if ((pcb->remote_port == src) && (ip_addr_isany_val(pcb->remote_ip) || - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + ip_addr_eq(&pcb->remote_ip, ip_current_src_addr()))) { /* the first fully matching PCB */ if (prev != NULL) { /* move the pcb to the front of udp_pcbs so that is @@ -321,7 +321,7 @@ udp_input(struct pbuf *p, struct netif *inp) #endif /* LWIP_IPV6 */ #if LWIP_IPV4 if (!ip_current_is_v6()) { - for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); + for_us = ip4_addr_eq(netif_ip4_addr(inp), ip4_current_dest_addr()); } #endif /* LWIP_IPV4 */ } @@ -365,7 +365,7 @@ udp_input(struct pbuf *p, struct netif *inp) #endif /* CHECKSUM_CHECK_UDP */ if (pbuf_remove_header(p, UDP_HLEN)) { /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); UDP_STATS_INC(udp.drop); MIB2_STATS_INC(mib2.udpinerrors); pbuf_free(p); @@ -570,7 +570,7 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, in pcb->mcast_ip4 that is used for routing. If this routing lookup fails, we try regular routing as though no override was set. */ if (!ip4_addr_isany_val(pcb->mcast_ip4) && - !ip4_addr_cmp(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) { + !ip4_addr_eq(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) { netif = ip4_route_src(ip_2_ip4(&pcb->local_ip), &pcb->mcast_ip4); } } @@ -678,7 +678,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_i } else { /* check if UDP PCB local IP address is correct * this could be an old address if netif->ip_addr has changed */ - if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { + if (!ip4_addr_eq(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { /* local_ip doesn't match, drop the packet */ return ERR_RTE; } @@ -911,7 +911,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d /** * @ingroup udp_raw * Bind an UDP PCB. - * + * * @param pcb UDP PCB to be bound with a local address ipaddr and port. * @param ipaddr local IP address to bind with. Use IP_ANY_TYPE to * bind to all local interfaces. @@ -988,7 +988,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { if (pcb != ipcb) { /* By default, we don't allow to bind to a port that any other udp - PCB is already bound to, unless *all* PCBs with that port have tha + PCB is already bound to, unless *all* PCBs with that port have the REUSEADDR flag set. */ #if SO_REUSE if (!ip_get_option(pcb, SOF_REUSEADDR) || @@ -999,7 +999,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) if ((ipcb->local_port == port) && (((IP_GET_TYPE(&ipcb->local_ip) == IP_GET_TYPE(ipaddr)) && /* IP address matches or any IP used? */ - (ip_addr_cmp(&ipcb->local_ip, ipaddr) || + (ip_addr_eq(&ipcb->local_ip, ipaddr) || ip_addr_isany(ipaddr) || ip_addr_isany(&ipcb->local_ip))) || (IP_GET_TYPE(&ipcb->local_ip) == IPADDR_TYPE_ANY) || @@ -1172,8 +1172,8 @@ udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) /** * @ingroup udp_raw - * Removes and deallocates the pcb. - * + * Removes and deallocates the pcb. + * * @param pcb UDP PCB to be removed. The PCB is removed from the list of * UDP PCB's and the data structure is freed from memory. * @@ -1238,6 +1238,7 @@ udp_new(void) #if LWIP_MULTICAST_TX_OPTIONS udp_set_multicast_ttl(pcb, UDP_TTL); #endif /* LWIP_MULTICAST_TX_OPTIONS */ + pcb_tci_init(pcb); } return pcb; } @@ -1288,7 +1289,7 @@ void udp_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_a if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&upcb->local_ip, old_addr)) { + if (ip_addr_eq(&upcb->local_ip, old_addr)) { /* The PCB is bound to the old ipaddr and * is set to bound to the new one instead */ ip_addr_copy(upcb->local_ip, *new_addr); diff --git a/src/lwip/acd.h b/src/lwip/acd.h new file mode 100644 index 0000000..e2e6cdd --- /dev/null +++ b/src/lwip/acd.h @@ -0,0 +1,109 @@ +/** + * @file + * + * ACD IPv4 Address Conflict Detection + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * Copyright (c) 2018 Jasper Verschueren + * 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: Jasper Verschueren + * Author: Dominik Spies + */ + +#ifndef LWIP_HDR_ACD_H +#define LWIP_HDR_ACD_H + +#include "lwip/opt.h" + +/* don't build if not configured for use in lwipopts.h */ +#if LWIP_IPV4 && LWIP_ACD + +#include "lwip/netif.h" +#include "lwip/etharp.h" +#include "lwip/prot/acd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** ACD Timing + * ACD_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 .... + */ +#define ACD_TMR_INTERVAL 100 + +/** + * Callback function: Handle conflict information from ACD module + * + * @param netif network interface to handle conflict information on + * @param state acd_callback_enum_t + */ +typedef void (*acd_conflict_callback_t)(struct netif *netif, acd_callback_enum_t state); + +/** ACD state information per netif */ +struct acd +{ + /** next acd module */ + struct acd *next; + /** the currently selected, probed, announced or used IP-Address */ + ip4_addr_t ipaddr; + /** current ACD state machine state */ + acd_state_enum_t state; + /** sent number of probes or announces, dependent on state */ + u8_t sent_num; + /** ticks to wait, tick is ACD_TMR_INTERVAL long */ + u16_t ttw; + /** ticks until a conflict can again be solved by defending */ + u8_t lastconflict; + /** total number of probed/used IP-Addresses that resulted in a conflict */ + u8_t num_conflicts; + /** callback function -> let's the acd user know if the address is good or + if a conflict is detected */ + acd_conflict_callback_t acd_conflict_callback; +}; + +err_t acd_add(struct netif *netif, struct acd *acd, + acd_conflict_callback_t acd_conflict_callback); +void acd_remove(struct netif *netif, struct acd *acd); +err_t acd_start(struct netif *netif, struct acd *acd, ip4_addr_t ipaddr); +err_t acd_stop(struct acd *acd); +void acd_arp_reply(struct netif *netif, struct etharp_hdr *hdr); +void acd_tmr(void); +void acd_network_changed_link_down(struct netif *netif); +void acd_netif_ip_addr_changed(struct netif *netif, const ip_addr_t *old_addr, + const ip_addr_t *new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_ACD */ + +#endif /* LWIP_HDR_ACD_H */ diff --git a/src/lwip/altcp.h b/src/lwip/altcp.h index 1b24544..11acaff 100644 --- a/src/lwip/altcp.h +++ b/src/lwip/altcp.h @@ -1,6 +1,6 @@ /** * @file - * Application layered TCP connection API (to be used from TCPIP thread)\n + * Application layered TCP connection API (to be used from TCPIP thread) * * This file contains the generic API. * For more details see @ref altcp_api. @@ -80,7 +80,8 @@ struct altcp_pcb { u8_t pollinterval; }; -/** @ingroup altcp */ +/** @ingroup altcp + * Struct containing an allocator and its state. */ typedef struct altcp_allocator_s { /** Allocator function */ altcp_new_fn alloc; diff --git a/src/lwip/altcp_tcp.h b/src/lwip/altcp_tcp.h index dbde584..ca47379 100644 --- a/src/lwip/altcp_tcp.h +++ b/src/lwip/altcp_tcp.h @@ -1,6 +1,6 @@ /** * @file - * Application layered TCP connection API (to be used from TCPIP thread)\n + * Application layered TCP connection API (to be used from TCPIP thread)
* This interface mimics the tcp callback API to the application while preventing * direct linking (much like virtual functions). * This way, an application can make use of other application layer protocols diff --git a/src/lwip/altcp_tls.h b/src/lwip/altcp_tls.h index ff797f2..fcb784d 100644 --- a/src/lwip/altcp_tls.h +++ b/src/lwip/altcp_tls.h @@ -51,6 +51,13 @@ #include "lwip/altcp.h" +/* check if mbedtls port is enabled */ +#include "lwip/apps/altcp_tls_mbedtls_opts.h" +/* allow session structure to be fully defined when using mbedtls port */ +#if LWIP_ALTCP_TLS_MBEDTLS +#include "mbedtls/ssl.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -63,7 +70,7 @@ struct altcp_tls_config; /** @ingroup altcp_tls * Create an ALTCP_TLS server configuration handle prepared for multiple certificates */ -struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count); +struct altcp_tls_config *altcp_tls_create_config_server(u8_t cert_count); /** @ingroup altcp_tls * Add a certificate to an ALTCP_TLS server configuration handle @@ -94,6 +101,15 @@ struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca, const u8_t *privkey_pass, size_t privkey_pass_len, const u8_t *cert, size_t cert_len); +/** @ingroup altcp_tls + * Configure ALPN TLS extension + * Example:
+ * static const char *g_alpn_protocols[] = { "x-amzn-mqtt-ca", NULL };
+ * tls_config = altcp_tls_create_config_client(ca, ca_len);
+ * altcp_tls_conf_alpn_protocols(tls_config, g_alpn_protocols);
+ */ +int altcp_tls_configure_alpn_protocols(struct altcp_tls_config *conf, const char **protos); + /** @ingroup altcp_tls * Free an ALTCP_TLS configuration handle */ @@ -123,7 +139,7 @@ struct altcp_pcb *altcp_tls_new(struct altcp_tls_config *config, u8_t ip_type); /** @ingroup altcp_tls * Create new ALTCP_TLS layer pcb and its inner tcp pcb. * Same as @ref altcp_tls_new but this allocator function fits to - * @ref altcp_allocator_t / @ref altcp_new.\n + * @ref altcp_allocator_t / @ref altcp_new.
'arg' must contain a struct altcp_tls_config *. */ struct altcp_pcb *altcp_tls_alloc(void *arg, u8_t ip_type); @@ -134,6 +150,43 @@ struct altcp_pcb *altcp_tls_alloc(void *arg, u8_t ip_type); */ void *altcp_tls_context(struct altcp_pcb *conn); +/** @ingroup altcp_tls + * ALTCP_TLS session handle, content depends on port (e.g. mbedtls) + */ +struct altcp_tls_session +#if LWIP_ALTCP_TLS_MBEDTLS +{ + mbedtls_ssl_session data; +} +#endif +; + +/** @ingroup altcp_tls + * Initialise a TLS session buffer. + * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session) + */ +void altcp_tls_init_session(struct altcp_tls_session *dest); + +/** @ingroup altcp_tls + * Save current connected session to reuse it later. Should be called after altcp_connect() succeeded. + * Return error if saving session fail. + * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session) + */ +err_t altcp_tls_get_session(struct altcp_pcb *conn, struct altcp_tls_session *dest); + +/** @ingroup altcp_tls + * Restore a previously saved session. Must be called before altcp_connect(). + * Return error if cannot restore session. + * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session) + */ +err_t altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *from); + +/** @ingroup altcp_tls + * Free allocated data inside a TLS session buffer. + * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session) + */ +void altcp_tls_free_session(struct altcp_tls_session *dest); + #ifdef __cplusplus } #endif diff --git a/src/lwip/api.h b/src/lwip/api.h index c2afaf2..be8c22a 100644 --- a/src/lwip/api.h +++ b/src/lwip/api.h @@ -153,27 +153,27 @@ enum netconn_state { }; /** Used to inform the callback function about changes - * + * * Event explanation: - * + * * In the netconn implementation, there are three ways to block a client: - * + * * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) - * + * * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking * connections, you need to know in advance whether a call to a netconn function call would block or not, * and these events tell you about that. - * - * RCVPLUS events say: Safe to perform a potentially blocking call call once more. + * + * RCVPLUS events say: Safe to perform a potentially blocking call call once more. * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe * to call netconn_accept 3 times without being blocked. * Same thing for receive mbox. - * + * * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". * Socket implementation decrements the counter. - * + * * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. @@ -246,10 +246,10 @@ struct netconn { all threads when closing while threads are waiting. */ int mbox_threads_waiting; #endif - /** only used for socket layer */ -#if LWIP_SOCKET - int socket; -#endif /* LWIP_SOCKET */ + union { + int socket; + void *ptr; + } callback_arg; #if LWIP_SO_SNDTIMEO /** timeout to wait for sending data (which means enqueueing data for sending in internal buffers) in milliseconds */ @@ -373,6 +373,9 @@ err_t netconn_err(struct netconn *conn); #define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u8_t)((conn)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0) #define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0) +#define netconn_set_callback_arg(conn, arg) do { (conn)->callback_arg.ptr = (arg); } while(0) +#define netconn_get_callback_arg(conn) ((conn)->callback_arg.ptr) + /** Set the blocking status of netconn calls (@todo: write/send is missing) */ #define netconn_set_nonblocking(conn, val) do { if(val) { \ netconn_set_flags(conn, NETCONN_FLAG_NON_BLOCKING); \ diff --git a/src/lwip/apps/altcp_tls_mbedtls_opts.h b/src/lwip/apps/altcp_tls_mbedtls_opts.h index 71aa599..e41301c 100644 --- a/src/lwip/apps/altcp_tls_mbedtls_opts.h +++ b/src/lwip/apps/altcp_tls_mbedtls_opts.h @@ -100,6 +100,12 @@ #define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS (60 * 60 * 24) #endif +/** Certificate verification mode: MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL (default), + * MBEDTLS_SSL_VERIFY_REQUIRED (recommended)*/ +#ifndef ALTCP_MBEDTLS_AUTHMODE +#define ALTCP_MBEDTLS_AUTHMODE MBEDTLS_SSL_VERIFY_OPTIONAL +#endif + #endif /* LWIP_ALTCP */ #endif /* LWIP_HDR_ALTCP_TLS_OPTS_H */ diff --git a/src/lwip/apps/fs.h b/src/lwip/apps/fs.h index 67b9a60..82b219a 100644 --- a/src/lwip/apps/fs.h +++ b/src/lwip/apps/fs.h @@ -1,8 +1,8 @@ /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, + * 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, @@ -11,21 +11,21 @@ * 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. + * 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 + * 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 * */ @@ -54,6 +54,7 @@ struct fsdata_chksum { #define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02 #define FS_FILE_FLAGS_HEADER_HTTPVER_1_1 0x04 #define FS_FILE_FLAGS_SSI 0x08 +#define FS_FILE_FLAGS_CUSTOM 0x10 /** Define FS_FILE_EXTENSION_T_DEFINED if you have typedef'ed to your private * pointer type (defaults to 'void' so the default usage is 'void*') @@ -66,17 +67,16 @@ struct fs_file { const char *data; int len; int index; +#if LWIP_HTTPD_FILE_EXTENSION /* pextension is free for implementations to hold private (extensional) arbitrary data, e.g. holding some file state or file system handle */ fs_file_extension *pextension; +#endif /* LWIP_HTTPD_FILE_EXTENSION */ #if HTTPD_PRECALCULATED_CHECKSUM const struct fsdata_chksum *chksum; u16_t chksum_count; #endif /* HTTPD_PRECALCULATED_CHECKSUM */ u8_t flags; -#if LWIP_HTTPD_CUSTOM_FILES - u8_t is_custom_file; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ #if LWIP_HTTPD_FILE_STATE void *state; #endif /* LWIP_HTTPD_FILE_STATE */ @@ -119,6 +119,19 @@ struct fsdata_file { #endif /* HTTPD_PRECALCULATED_CHECKSUM */ }; +#if LWIP_HTTPD_CUSTOM_FILES +/* Prototypes required to implement custom files as fs addon */ +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 */ + #ifdef __cplusplus } #endif diff --git a/src/lwip/apps/http_client.h b/src/lwip/apps/http_client.h index 8a06308..3ba6d80 100644 --- a/src/lwip/apps/http_client.h +++ b/src/lwip/apps/http_client.h @@ -52,8 +52,8 @@ extern "C" { #endif /** - * @ingroup httpc - * HTTPC_HAVE_FILE_IO: define this to 1 to have functions dowloading directly + * @ingroup httpc + * HTTPC_HAVE_FILE_IO: define this to 1 to have functions downloading directly * to disk via fopen/fwrite. * These functions are example implementations of the interface only. */ @@ -62,13 +62,13 @@ extern "C" { #endif /** - * @ingroup httpc + * @ingroup httpc * The default TCP port used for HTTP */ #define HTTP_DEFAULT_PORT LWIP_IANA_PORT_HTTP /** - * @ingroup httpc + * @ingroup httpc * HTTP client result codes */ typedef enum ehttpc_result { @@ -97,7 +97,7 @@ typedef enum ehttpc_result { typedef struct _httpc_state httpc_state_t; /** - * @ingroup httpc + * @ingroup httpc * Prototype of a http client callback function * * @param arg argument specified when initiating the request @@ -110,13 +110,13 @@ typedef struct _httpc_state httpc_state_t; typedef void (*httpc_result_fn)(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err); /** - * @ingroup httpc + * @ingroup httpc * Prototype of http client callback: called when the headers are received * * @param connection http client connection * @param arg argument specified when initiating the request * @param hdr header pbuf(s) (may contain data also) - * @param hdr_len length of the heders in 'hdr' + * @param hdr_len length of the headers in 'hdr' * @param content_len content length as received in the headers (-1 if not received) * @return if != ERR_OK is returned, the connection is aborted */ diff --git a/src/lwip/apps/httpd.h b/src/lwip/apps/httpd.h index e872429..1ecdd74 100644 --- a/src/lwip/apps/httpd.h +++ b/src/lwip/apps/httpd.h @@ -95,6 +95,7 @@ typedef struct tCGIHandler pfnCGIHandler; } tCGI; +/** Set the array of cgi handlers. */ void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); #endif /* LWIP_HTTPD_CGI */ diff --git a/src/lwip/apps/httpd_opts.h b/src/lwip/apps/httpd_opts.h index 8723961..2b66e67 100644 --- a/src/lwip/apps/httpd_opts.h +++ b/src/lwip/apps/httpd_opts.h @@ -94,7 +94,7 @@ * * To save memory, the maximum tag length is limited (@see LWIP_HTTPD_MAX_TAG_NAME_LEN). * To save memory, the maximum insertion string length is limited (@see - * LWIP_HTTPD_MAX_TAG_INSERT_LEN). If this is not enought, @ref LWIP_HTTPD_SSI_MULTIPART + * LWIP_HTTPD_MAX_TAG_INSERT_LEN). If this is not enough, @ref LWIP_HTTPD_SSI_MULTIPART * can be used. */ #if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ @@ -112,7 +112,9 @@ /** Set this to 0 to prevent parsing the file extension at runtime to decide * if a file should be scanned for SSI tags or not. * Default is 1 (file extensions are checked using the g_pcSSIExtensions array) - * Set to 2 to override this runtime test function. + * Set to 2 to override this runtime test function. In this case, you have to + * provide an external function that does the check: + * u8_t http_uri_is_ssi(struct fs_file *file, const char *uri) * * This is enabled by default, but if you only use a newer version of makefsdata * supporting the "-ssi" option, this info is already present in @@ -121,6 +123,14 @@ #define LWIP_HTTPD_SSI_BY_FILE_EXTENSION 1 #endif +/** This is a list of file extensions handled as SSI files. This define + * is used to initialize a 'const char *const[]'. It is only used if + * LWIP_HTTPD_SSI_BY_FILE_EXTENSION != 0. + */ +#if !defined LWIP_HTTPD_SSI_EXTENSIONS || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_EXTENSIONS ".shtml", ".shtm", ".ssi", ".xml", ".json" +#endif + /** Set this to 1 to support HTTP POST */ #if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ #define LWIP_HTTPD_SUPPORT_POST 0 @@ -175,7 +185,7 @@ #define HTTPD_DEBUG LWIP_DBG_OFF #endif -/** Set this to 1 to use a memp pool for allocating +/** Set this to 1 to use a memp pool for allocating * struct http_state instead of the heap. * If enabled, you'll need to define MEMP_NUM_PARALLEL_HTTPD_CONNS * (and MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS for SSI) to set the size of @@ -365,6 +375,16 @@ #define LWIP_HTTPD_FILE_STATE 0 #endif +/** Set this to 1 to add the pextension field to the fs_file structure. + * This is included here to retain compatibility with legacy code that + * relies on the presence of the pextension field. + * New code should use LWIP_HTTPD_FILE_STATE instead. + * This option may be removed in a future version of lwip. + */ +#if !defined LWIP_HTTPD_FILE_EXTENSION || defined __DOXYGEN__ +#define LWIP_HTTPD_FILE_EXTENSION 0 +#endif + /** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for * predefined (MSS-sized) chunks of the files to prevent having to calculate * the checksums at runtime. */ diff --git a/src/lwip/apps/lwiperf.h b/src/lwip/apps/lwiperf.h index cc86e7f..e6f4476 100644 --- a/src/lwip/apps/lwiperf.h +++ b/src/lwip/apps/lwiperf.h @@ -76,7 +76,16 @@ enum lwiperf_client_type /** Prototype of a report function that is called when a session is finished. This report function can show the test results. - @param report_type contains the test result */ + @param arg Report_arg from when the test was started. + @param report_type contains the test result + @param local_addr The local address from the session + @param local_port The local port + @param remote_addr The remote address from the session + @param remote_port The remote port + @param bytes_transferred Total transferred bytes + @param ms_duration Total session duration, in milliseconds + @param bandwidth_kbitpsec Average bandwidth during the session, in kbps +*/ typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); diff --git a/src/lwip/apps/mdns.h b/src/lwip/apps/mdns.h index 20d7ee2..33da4a3 100644 --- a/src/lwip/apps/mdns.h +++ b/src/lwip/apps/mdns.h @@ -32,6 +32,7 @@ * This file is part of the lwIP TCP/IP stack. * * Author: Erik Ekman + * Author: Jasper Verschueren * */ @@ -56,10 +57,41 @@ enum mdns_sd_proto { #define MDNS_PROBING_SUCCESSFUL 1 #define MDNS_LABEL_MAXLEN 63 +#define MDNS_DOMAIN_MAXLEN 256 struct mdns_host; struct mdns_service; +/* Domain structs */ +struct mdns_domain { + /* Encoded domain name */ + u8_t name[MDNS_DOMAIN_MAXLEN]; + /* Total length of domain name, including zero */ + u16_t length; + /* Set if compression of this domain is not allowed */ + u8_t skip_compression; +}; + +/** 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_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; +}; + /** Callback function to add text to a reply, called when generating the reply */ typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); @@ -67,22 +99,26 @@ typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_use * uniqueness, called with result MDNS_PROBING_SUCCESSFUL if no other node claimed * use for the name for the netif or a service and is safe to use, or MDNS_PROBING_CONFLICT * if another node is already using it and mdns is disabled on this interface */ -typedef void (*mdns_name_result_cb_t)(struct netif* netif, u8_t result); +typedef void (*mdns_name_result_cb_t)(struct netif* netif, u8_t result, s8_t slot); + +void *mdns_get_service_txt_userdata(struct netif *netif, s8_t slot); void mdns_resp_init(void); void mdns_resp_register_name_result_cb(mdns_name_result_cb_t cb); -err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); +err_t mdns_resp_add_netif(struct netif *netif, const char *hostname); err_t mdns_resp_remove_netif(struct netif *netif); err_t mdns_resp_rename_netif(struct netif *netif, const char *hostname); +int mdns_resp_netif_active(struct netif *netif); -s8_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); -err_t mdns_resp_del_service(struct netif *netif, s8_t slot); -err_t mdns_resp_rename_service(struct netif *netif, s8_t slot, const char *name); +s8_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_userdata); +err_t mdns_resp_del_service(struct netif *netif, u8_t slot); +err_t mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name); err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); +void mdns_resp_restart_delay(struct netif *netif, uint32_t delay); void mdns_resp_restart(struct netif *netif); void mdns_resp_announce(struct netif *netif); @@ -96,6 +132,19 @@ void mdns_resp_announce(struct netif *netif); */ #define mdns_resp_netif_settings_changed(netif) mdns_resp_announce(netif) +#if LWIP_MDNS_SEARCH +typedef void (*search_result_fn_t)(struct mdns_answer *answer, const char *varpart, int varlen, int flags, void *arg); +/* flags bits, both can be set! */ +#define MDNS_SEARCH_RESULT_FIRST 1 /* First answer in received frame. */ +#define MDNS_SEARCH_RESULT_LAST 2 /* Last answer. */ + +err_t mdns_search_service(const char *name, const char *service, enum mdns_sd_proto proto, + struct netif *netif, search_result_fn_t result_fn, void *arg, + u8_t *request_id); +void mdns_search_stop(u8_t request_id); + +#endif /* LWIP_MDNS_SEARCH */ + #endif /* LWIP_MDNS_RESPONDER */ #ifdef __cplusplus diff --git a/src/lwip/apps/mdns_domain.h b/src/lwip/apps/mdns_domain.h new file mode 100644 index 0000000..9fa804e --- /dev/null +++ b/src/lwip/apps/mdns_domain.h @@ -0,0 +1,80 @@ +/** + * @file + * MDNS responder - domain related functionalities + */ + + /* + * 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 + * Author: Jasper Verschueren + * + */ + +#ifndef LWIP_HDR_APPS_MDNS_DOMAIN_H +#define LWIP_HDR_APPS_MDNS_DOMAIN_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/apps/mdns_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MDNS_RESPONDER + +/* Domain methods - also visible for unit tests */ + +err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); +err_t mdns_domain_add_domain(struct mdns_domain *domain, struct mdns_domain *source); +err_t mdns_domain_add_string(struct mdns_domain *domain, const char *source); +u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); +void mdns_domain_debug_print(struct mdns_domain *domain); +int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); +#if LWIP_IPV4 +err_t mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr); +#endif +#if LWIP_IPV6 +err_t mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr); +#endif +err_t mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns); +err_t mdns_build_dnssd_domain(struct mdns_domain *domain); +err_t mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name); +#if LWIP_MDNS_SEARCH +err_t mdns_build_request_domain(struct mdns_domain *domain, struct mdns_request *request, int include_name); +#endif +u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); +err_t mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain); + +#endif /* LWIP_MDNS_RESPONDER */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MDNS_DOMAIN_H */ diff --git a/src/lwip/apps/mdns_opts.h b/src/lwip/apps/mdns_opts.h index 45f2c50..1eee3e3 100644 --- a/src/lwip/apps/mdns_opts.h +++ b/src/lwip/apps/mdns_opts.h @@ -32,6 +32,7 @@ * This file is part of the lwIP TCP/IP stack. * * Author: Erik Ekman + * Author: Jasper Verschueren * */ @@ -59,6 +60,34 @@ #define MDNS_MAX_SERVICES 1 #endif +/** The minimum delay between probes in ms. RFC 6762 require 250ms. + * In noisy WiFi environment, adding 30-50ms to this value help a lot for + * a successful Apple BCT tests. + */ +#ifndef MDNS_PROBE_DELAY_MS +#define MDNS_PROBE_DELAY_MS 250 +#endif + +/** The maximum number of received packets stored in chained list of known + * answers for pending truncated questions. This value define the size of + * the MDNS_PKTS mempool. + * Up to MDNS_MAX_STORED_PKTS pbuf can be stored in addition to TC questions + * that are pending. + */ +#ifndef MDNS_MAX_STORED_PKTS +#define MDNS_MAX_STORED_PKTS 4 +#endif + +/** Payload size allocated for each outgoing UDP packet. Will be allocated with + * PBUF_RAM and freed after packet was sent. + * According to RFC 6762, there is no reason to retain the 512 bytes restriction + * for link-local multicast packet. + * 512 bytes isn't enough when 2 services need to be probed. + */ +#ifndef MDNS_OUTPUT_PACKET_SIZE +#define MDNS_OUTPUT_PACKET_SIZE ((MDNS_MAX_SERVICES == 1) ? 512 : 1450) +#endif + /** MDNS_RESP_USENETIF_EXTCALLBACK==1: register an ext_callback on the netif * to automatically restart probing/announcing on status or address change. */ @@ -66,6 +95,18 @@ #define MDNS_RESP_USENETIF_EXTCALLBACK LWIP_NETIF_EXT_STATUS_CALLBACK #endif +/** + * LWIP_MDNS_SEARCH==1: Turn on search over multicast DNS module. + */ +#ifndef LWIP_MDNS_SEARCH +#define LWIP_MDNS_SEARCH 1 +#endif + +/** The maximum number of running requests */ +#ifndef MDNS_MAX_REQUESTS +#define MDNS_MAX_REQUESTS 2 +#endif + /** * MDNS_DEBUG: Enable debugging for multicast DNS. */ @@ -78,4 +119,3 @@ */ #endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ - diff --git a/src/lwip/apps/mdns_out.h b/src/lwip/apps/mdns_out.h new file mode 100644 index 0000000..e6a7e38 --- /dev/null +++ b/src/lwip/apps/mdns_out.h @@ -0,0 +1,138 @@ +/** + * @file + * MDNS responder - output related functionalities + */ + + /* + * 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 + * Author: Jasper Verschueren + * + */ + +#ifndef LWIP_HDR_APPS_MDNS_OUT_H +#define LWIP_HDR_APPS_MDNS_OUT_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/apps/mdns_priv.h" +#include "lwip/netif.h" +#include "lwip/timeouts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MDNS_RESPONDER + +/** Bitmasks outmsg generation */ +/* Probe for ALL types with hostname */ +#define QUESTION_PROBE_HOST_ANY 0x10 +/* Probe for ALL types with service instance name */ +#define QUESTION_PROBE_SERVICE_NAME_ANY 0x10 + +/* 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 + +/* RFC6762 section 6: + * To protect the network against excessive packet flooding due to software bugs + * or malicious attack, a Multicast DNS responder MUST NOT (except in the one + * special case of answering probe queries) multicast a record on a given + * interface until at least one second has elapsed since the last time that + * record was multicast on that particular interface. + */ +#define MDNS_MULTICAST_TIMEOUT 1000 + +/* RFC6762 section 6: + * In this special case only, when responding via multicast to a probe, a + * Multicast DNS responder is only required to delay its transmission as + * necessary to ensure an interval of at least 250 ms since the last time the + * record was multicast on that interface. + */ +#define MDNS_MULTICAST_PROBE_TIMEOUT 250 + +/* RFC6762 section 5.4: + * When receiving a question with the unicast-response bit set, a responder + * SHOULD usually respond with a unicast packet directed back to the querier. + * However, if the responder has not multicast that record recently (within one + * quarter of its TTL), then the responder SHOULD instead multicast the response + * so as to keep all the peer caches up to date, and to permit passive conflict + * detection. + * -> we implement a stripped down version. Depending on a timeout of 30s + * (25% of 120s) all QU questions are send via multicast or unicast. + */ +#define MDNS_MULTICAST_TIMEOUT_25TTL 30000 + +err_t mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg, + struct mdns_outpacket *outpkt); +err_t mdns_send_outpacket(struct mdns_outmsg *msg, struct netif *netif); +void mdns_set_timeout(struct netif *netif, u32_t msecs, + sys_timeout_handler handler, u8_t *busy_flag); +#if LWIP_IPV4 +void mdns_multicast_timeout_reset_ipv4(void *arg); +void mdns_multicast_probe_timeout_reset_ipv4(void *arg); +void mdns_multicast_timeout_25ttl_reset_ipv4(void *arg); +void mdns_send_multicast_msg_delayed_ipv4(void *arg); +void mdns_send_unicast_msg_delayed_ipv4(void *arg); +void mdns_start_multicast_timeouts_ipv4(struct netif *netif); +#endif +#if LWIP_IPV6 +void mdns_multicast_timeout_reset_ipv6(void *arg); +void mdns_multicast_probe_timeout_reset_ipv6(void *arg); +void mdns_multicast_timeout_25ttl_reset_ipv6(void *arg); +void mdns_send_multicast_msg_delayed_ipv6(void *arg); +void mdns_send_unicast_msg_delayed_ipv6(void *arg); +void mdns_start_multicast_timeouts_ipv6(struct netif *netif); +#endif +void mdns_prepare_txtdata(struct mdns_service *service); +#ifdef LWIP_MDNS_SEARCH +err_t mdns_send_request(struct mdns_request *req, struct netif *netif, const ip_addr_t *destination); +#endif + +#endif /* LWIP_MDNS_RESPONDER */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MDNS_OUT_H */ diff --git a/src/lwip/apps/mdns_priv.h b/src/lwip/apps/mdns_priv.h index 9635b5b..5209ba0 100644 --- a/src/lwip/apps/mdns_priv.h +++ b/src/lwip/apps/mdns_priv.h @@ -32,11 +32,13 @@ * This file is part of the lwIP TCP/IP stack. * * Author: Erik Ekman + * Author: Jasper Verschueren * */ #ifndef LWIP_HDR_MDNS_PRIV_H #define LWIP_HDR_MDNS_PRIV_H +#include "lwip/apps/mdns.h" #include "lwip/apps/mdns_opts.h" #include "lwip/pbuf.h" @@ -46,24 +48,185 @@ extern "C" { #if LWIP_MDNS_RESPONDER -/* Domain struct and methods - visible for unit tests */ - -#define MDNS_DOMAIN_MAXLEN 256 #define MDNS_READNAME_ERROR 0xFFFF +#define NUM_DOMAIN_OFFSETS 10 + +#define SRV_PRIORITY 0 +#define SRV_WEIGHT 0 + +/* mDNS TTL: (RFC6762 section 10) + * - 120 seconds if the hostname appears somewhere in the RR + * - 75 minutes if not (4500 seconds) + * - 10 seconds if responding to a legacy query + */ +#define MDNS_TTL_10 10 +#define MDNS_TTL_120 120 +#define MDNS_TTL_4500 4500 + +/* RFC6762 section 8.1: If fifteen conflicts occur within any ten-second period, + * then the host MUST wait at least five seconds before each successive + * additional probe attempt. + */ +#define MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT 15 +#define MDNS_PROBE_MAX_CONFLICTS_TIME_WINDOW 10000 +#define MDNS_PROBE_MAX_CONFLICTS_TIMEOUT 5000 + +#if LWIP_MDNS_SEARCH +/** Description of a search request */ +struct mdns_request { + /** Name of service, like 'myweb' */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Type of service, like '_http' or '_services._dns-sd' */ + struct mdns_domain service; + /** Callback function called for each response */ + search_result_fn_t result_fn; + void *arg; + /** Protocol, TCP or UDP */ + u16_t proto; + /** Query type (PTR, SRV, ...) */ + u8_t qtype; + /** PTR only request. */ + u16_t only_ptr; +}; +#endif + +/** 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; + /** Protocol, TCP or UDP */ + u16_t proto; + /** Port of the service */ + u16_t port; +}; -struct mdns_domain { - /* Encoded domain name */ - u8_t name[MDNS_DOMAIN_MAXLEN]; - /* Total length of domain name, including zero */ - u16_t length; - /* Set if compression of this domain is not allowed */ - u8_t skip_compression; +/** mDNS output packet */ +struct mdns_outpacket { + /** Packet data */ + struct pbuf *pbuf; + /** Current write offset in packet */ + u16_t write_offset; + /** Number of questions written */ + u16_t questions; + /** Number of normal answers written */ + u16_t answers; + /** Number of authoritative answers written */ + u16_t authoritative; + /** 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]; +}; + +/** mDNS output message */ +struct mdns_outmsg { + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** dns flags */ + u8_t flags; + /** Destination IP/port if sent unicast */ + ip_addr_t dest_addr; + u16_t dest_port; + /** If all answers in packet should set cache_flush bit */ + u8_t cache_flush; + /** If reply should be sent unicast (as requested) */ + u8_t unicast_reply_requested; + /** If legacy query. (tx_id needed, and write + * question again in reply before answer) */ + u8_t legacy_query; + /** If the query is a probe msg we need to respond immediately. Independent of + * the QU or QM flag. */ + u8_t probe_query_recv; + /* Question bitmask for host information */ + u8_t host_questions; + /* Questions bitmask per service */ + u8_t serv_questions[MDNS_MAX_SERVICES]; + /* 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]; +#ifdef LWIP_MDNS_SEARCH + /** Search query to send */ + struct mdns_request *query; +#endif +}; + +/** Delayed msg info */ +struct mdns_delayed_msg { + /** Signals if a multicast msg needs to be send out */ + u8_t multicast_msg_waiting; + /** Multicast timeout for all multicast traffic except probe answers */ + u8_t multicast_timeout; + /** Multicast timeout only for probe answers */ + u8_t multicast_probe_timeout; + /** Output msg used for delayed multicast responses */ + struct mdns_outmsg delayed_msg_multicast; + /** Prefer multicast over unicast timeout -> 25% of TTL = we take 30s as + general delay. */ + u8_t multicast_timeout_25TTL; + /** Only send out new unicast message if previous was send */ + u8_t unicast_msg_in_use; + /** Output msg used for delayed unicast responses */ + struct mdns_outmsg delayed_msg_unicast; +}; + +/* MDNS states */ +typedef enum { + /* MDNS module is off */ + MDNS_STATE_OFF, + /* Waiting before probing can be started */ + MDNS_STATE_PROBE_WAIT, + /* Probing the unique records */ + MDNS_STATE_PROBING, + /* Waiting before announcing the probed unique records */ + MDNS_STATE_ANNOUNCE_WAIT, + /* Announcing all records */ + MDNS_STATE_ANNOUNCING, + /* Probing and announcing completed */ + MDNS_STATE_COMPLETE +} mdns_resp_state_enum_t; + +/** 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]; + /** Number of probes/announces sent for the current name */ + u8_t sent_num; + /** State of the mdns responder */ + mdns_resp_state_enum_t state; +#if LWIP_IPV4 + /** delayed msg struct for IPv4 */ + struct mdns_delayed_msg ipv4; +#endif +#if LWIP_IPV6 + /** delayed msg struct for IPv6 */ + struct mdns_delayed_msg ipv6; +#endif + /** Timestamp of probe conflict saved in list */ + u32_t conflict_time[MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT]; + /** Rate limit flag */ + u8_t rate_limit_activated; + /** List index for timestamps */ + u8_t index; + /** number of conflicts since startup */ + u8_t num_conflicts; }; -err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); -u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); -int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); -u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); +struct mdns_host* netif_mdns_data(struct netif *netif); +struct udp_pcb* get_mdns_pcb(void); #endif /* LWIP_MDNS_RESPONDER */ diff --git a/src/lwip/apps/mqtt.h b/src/lwip/apps/mqtt.h index c2bb228..f1583fc 100644 --- a/src/lwip/apps/mqtt.h +++ b/src/lwip/apps/mqtt.h @@ -79,6 +79,8 @@ struct mqtt_connect_client_info_t { const char* will_topic; /** will_msg, see will_topic */ const char* will_msg; + /** will_msg length, 0 to compute length from will_msg string */ + u8_t will_msg_len; /** will_qos, see will_topic */ u8_t will_qos; /** will_retain, see will_topic */ @@ -134,7 +136,7 @@ enum { MQTT_DATA_FLAG_LAST = 1 }; -/** +/** * @ingroup mqtt * Function prototype for MQTT incoming publish data callback function. Called when data * arrives to a subscribed topic @see mqtt_subscribe @@ -149,7 +151,7 @@ enum { typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); -/** +/** * @ingroup mqtt * Function prototype for MQTT incoming publish function. Called when an incoming publish * arrives to a subscribed topic @see mqtt_subscribe @@ -183,7 +185,7 @@ void mqtt_client_free(mqtt_client_t* client); u8_t mqtt_client_is_connected(mqtt_client_t *client); -void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, +void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, mqtt_incoming_data_cb_t data_cb, void *arg); err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); diff --git a/src/lwip/apps/netbiosns_opts.h b/src/lwip/apps/netbiosns_opts.h index 1f51ab0..cc0da95 100644 --- a/src/lwip/apps/netbiosns_opts.h +++ b/src/lwip/apps/netbiosns_opts.h @@ -42,7 +42,7 @@ /** NetBIOS name of lwip device * This must be uppercase until NETBIOS_STRCMP() is defined to a string - * comparision function that is case insensitive. + * comparison function that is case insensitive. * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") * diff --git a/src/lwip/apps/smtp_opts.h b/src/lwip/apps/smtp_opts.h index bc743f6..c588fb9 100644 --- a/src/lwip/apps/smtp_opts.h +++ b/src/lwip/apps/smtp_opts.h @@ -6,14 +6,14 @@ #ifdef __cplusplus extern "C" { #endif - + /** * @defgroup smtp_opts Options * @ingroup smtp - * + * * @{ */ - + /** Set this to 1 to enable data handler callback on BODY */ #ifndef SMTP_BODYDH #define SMTP_BODYDH 0 @@ -78,4 +78,3 @@ extern "C" { #endif #endif /* SMTP_OPTS_H */ - diff --git a/src/lwip/apps/snmp.h b/src/lwip/apps/snmp.h index a3f8eb1..d01f99b 100644 --- a/src/lwip/apps/snmp.h +++ b/src/lwip/apps/snmp.h @@ -50,13 +50,11 @@ extern "C" { #include "lwip/err.h" #include "lwip/apps/snmp_core.h" -/** SNMP variable binding descriptor (publically needed for traps) */ +/** SNMP variable binding descriptor (publicly needed for traps) */ struct snmp_varbind { /** pointer to next varbind, NULL for last in list */ struct snmp_varbind *next; - /** pointer to previous varbind, NULL for first in list */ - struct snmp_varbind *prev; /** object identifier */ struct snmp_obj_id oid; @@ -101,6 +99,16 @@ err_t snmp_send_trap_generic(s32_t generic_trap); err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); +err_t snmp_send_inform_generic(s32_t generic_trap, struct snmp_varbind *varbinds, s32_t *ptr_request_id); +err_t snmp_send_inform_specific(s32_t specific_trap, struct snmp_varbind *varbinds, s32_t *ptr_request_id); +err_t snmp_send_inform(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds, s32_t *ptr_request_id); +struct snmp_request; +typedef void (*snmp_inform_callback_fct)(struct snmp_request *request, void* callback_arg); +void snmp_set_inform_callback(snmp_inform_callback_fct inform_callback, void* callback_arg); + +void snmp_set_default_trap_version(u8_t snmp_version); +u8_t snmp_get_default_trap_version(void); + #define SNMP_AUTH_TRAPS_DISABLED 0 #define SNMP_AUTH_TRAPS_ENABLED 1 void snmp_set_auth_traps_enabled(u8_t enable); diff --git a/src/lwip/apps/snmp_core.h b/src/lwip/apps/snmp_core.h index 6021c72..5a8a49f 100644 --- a/src/lwip/apps/snmp_core.h +++ b/src/lwip/apps/snmp_core.h @@ -101,7 +101,7 @@ extern "C" { /** error codes predefined by SNMP prot. */ typedef enum { SNMP_ERR_NOERROR = 0, -/* +/* outdated v1 error codes. do not use anmore! #define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead #define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead diff --git a/src/lwip/apps/snmp_mib2.h b/src/lwip/apps/snmp_mib2.h index 2f4a689..453e519 100644 --- a/src/lwip/apps/snmp_mib2.h +++ b/src/lwip/apps/snmp_mib2.h @@ -60,7 +60,7 @@ extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; #define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) #endif -void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ +void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be definition */ void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); diff --git a/src/lwip/apps/snmp_threadsync.h b/src/lwip/apps/snmp_threadsync.h index a25dbf2..76f1118 100644 --- a/src/lwip/apps/snmp_threadsync.h +++ b/src/lwip/apps/snmp_threadsync.h @@ -72,7 +72,7 @@ struct threadsync_data struct snmp_node_instance proxy_instance; }; -/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ +/** Thread sync instance. Needed EXACTLY once for every thread to be synced into. */ struct snmp_threadsync_instance { sys_sem_t sem; diff --git a/src/lwip/apps/sntp.h b/src/lwip/apps/sntp.h index c415253..11dacce 100644 --- a/src/lwip/apps/sntp.h +++ b/src/lwip/apps/sntp.h @@ -57,6 +57,7 @@ u8_t sntp_enabled(void); void sntp_setserver(u8_t idx, const ip_addr_t *addr); const ip_addr_t* sntp_getserver(u8_t idx); +u8_t sntp_getkodreceived(u8_t idx); #if SNTP_MONITOR_SERVER_REACHABILITY u8_t sntp_getreachability(u8_t idx); diff --git a/src/lwip/apps/sntp_opts.h b/src/lwip/apps/sntp_opts.h index cb62771..1fad9a8 100644 --- a/src/lwip/apps/sntp_opts.h +++ b/src/lwip/apps/sntp_opts.h @@ -158,14 +158,14 @@ /** SNTP receive timeout - in milliseconds * Also used as retry timeout - this shouldn't be too low. - * Default is 15 seconds. Must not be beolw 15 seconds by specification (i.e. 15000) + * Default is 15 seconds. Must not be below 15 seconds by specification (i.e. 15000) */ #if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ #define SNTP_RECV_TIMEOUT 15000 #endif /** SNTP update delay - in milliseconds - * Default is 1 hour. Must not be beolw 60 seconds by specification (i.e. 60000) + * Default is 1 hour. Must not be below 60 seconds by specification (i.e. 60000) */ #if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ #define SNTP_UPDATE_DELAY 3600000 diff --git a/src/lwip/apps/tftp_client.h b/src/lwip/apps/tftp_client.h new file mode 100644 index 0000000..24dbda6 --- /dev/null +++ b/src/lwip/apps/tftp_client.h @@ -0,0 +1,50 @@ +/** + * + * @file tftp_client.h + * TFTP client header + * + */ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_CLIENT_H +#define LWIP_HDR_APPS_TFTP_CLIENT_H + +#include "lwip/apps/tftp_common.h" + +enum tftp_transfer_mode { + TFTP_MODE_OCTET, + TFTP_MODE_NETASCII, + TFTP_MODE_BINARY /* used in old versions only */ +}; + +err_t tftp_init_client(const struct tftp_context* ctx); +err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); +err_t tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); + +#endif /* LWIP_HDR_APPS_TFTP_CLIENT_H */ diff --git a/src/lwip/apps/tftp_common.h b/src/lwip/apps/tftp_common.h new file mode 100644 index 0000000..4bc2c17 --- /dev/null +++ b/src/lwip/apps/tftp_common.h @@ -0,0 +1,108 @@ +/** + * + * @file tftp_common.h + * + * @author Logan Gunthorpe + * + * @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 + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_COMMON_H +#define LWIP_HDR_APPS_TFTP_COMMON_H + +#include "lwip/apps/tftp_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup tftp + * TFTP context containing callback functions for TFTP transfers + */ +struct tftp_context { + /** + * Open file for read/write (server mode only). + * @param fname Filename + * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) + * @param write Flag indicating read (0) or write (!= 0) access + * @returns File handle supplied to other functions + */ + void* (*open)(const char* fname, const char* mode, u8_t write); + /** + * Close file handle + * @param handle File handle returned by open()/tftp_put()/tftp_get() + */ + void (*close)(void* handle); + /** + * Read from file + * @param handle File handle returned by open()/tftp_put()/tftp_get() + * @param buf Target buffer to copy read data to + * @param bytes Number of bytes to copy to buf + * @returns >= 0: Success; < 0: Error + */ + int (*read)(void* handle, void* buf, int bytes); + /** + * Write to file + * @param handle File handle returned by open()/tftp_put()/tftp_get() + * @param pbuf PBUF adjusted such that payload pointer points + * to the beginning of write data. In other words, + * TFTP headers are stripped off. + * @returns >= 0: Success; < 0: Error + */ + int (*write)(void* handle, struct pbuf* p); + /** + * Error indication from client or response from server + * @param handle File handle set by open()/tftp_get()/tftp_put() + * @param err error code from client or server + * @param msg error message from client or server + * @param size size of msg + */ + void (*error)(void* handle, int err, const char* msg, int size); +}; + +#define LWIP_TFTP_MODE_SERVER 0x01 +#define LWIP_TFTP_MODE_CLIENT 0x02 +#define LWIP_TFTP_MODE_CLIENTSERVER (LWIP_TFTP_MODE_SERVER | LWIP_TFTP_MODE_CLIENT) + +err_t tftp_init_common(u8_t mode, const struct tftp_context* ctx); +void tftp_cleanup(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_TFTP_COMMON_H */ diff --git a/src/lwip/apps/tftp_opts.h b/src/lwip/apps/tftp_opts.h index 198f632..509fabd 100644 --- a/src/lwip/apps/tftp_opts.h +++ b/src/lwip/apps/tftp_opts.h @@ -11,7 +11,7 @@ * */ -/* +/* * Redistribution and use in source and binary forms, with or without * modification,are permitted provided that the following conditions are met: * @@ -96,7 +96,7 @@ * Max. length of TFTP mode */ #if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ -#define TFTP_MAX_MODE_LEN 7 +#define TFTP_MAX_MODE_LEN 10 #endif /** diff --git a/src/lwip/apps/tftp_server.h b/src/lwip/apps/tftp_server.h index 0a7fbee..a5769ce 100644 --- a/src/lwip/apps/tftp_server.h +++ b/src/lwip/apps/tftp_server.h @@ -1,17 +1,11 @@ /** * * @file tftp_server.h - * - * @author Logan Gunthorpe - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. + * TFTP server header * */ -/* +/* * Redistribution and use in source and binary forms, with or without * modification,are permitted provided that the following conditions are met: * @@ -34,62 +28,15 @@ * 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 + * This file is part of the lwIP TCP/IP stack. * */ #ifndef LWIP_HDR_APPS_TFTP_SERVER_H #define LWIP_HDR_APPS_TFTP_SERVER_H -#include "lwip/apps/tftp_opts.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @ingroup tftp - * TFTP context containing callback functions for TFTP transfers - */ -struct tftp_context { - /** - * Open file for read/write. - * @param fname Filename - * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) - * @param write Flag indicating read (0) or write (!= 0) access - * @returns File handle supplied to other functions - */ - void* (*open)(const char* fname, const char* mode, u8_t write); - /** - * Close file handle - * @param handle File handle returned by open() - */ - void (*close)(void* handle); - /** - * Read from file - * @param handle File handle returned by open() - * @param buf Target buffer to copy read data to - * @param bytes Number of bytes to copy to buf - * @returns >= 0: Success; < 0: Error - */ - int (*read)(void* handle, void* buf, int bytes); - /** - * Write to file - * @param handle File handle returned by open() - * @param pbuf PBUF adjusted such that payload pointer points - * to the beginning of write data. In other words, - * TFTP headers are stripped off. - * @returns >= 0: Success; < 0: Error - */ - int (*write)(void* handle, struct pbuf* p); -}; - -err_t tftp_init(const struct tftp_context* ctx); -void tftp_cleanup(void); +#include "lwip/apps/tftp_common.h" -#ifdef __cplusplus -} -#endif +err_t tftp_init_server(const struct tftp_context* ctx); #endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/src/lwip/arch.h b/src/lwip/arch.h index 58dae33..c659a80 100644 --- a/src/lwip/arch.h +++ b/src/lwip/arch.h @@ -72,9 +72,9 @@ #define LWIP_RAND() ((u32_t)rand()) #endif -/** Platform specific diagnostic output.\n +/** Platform specific diagnostic output.
* Note the default implementation pulls in printf, which may - * in turn pull in a lot of standard libary code. In resource-constrained + * in turn pull in a lot of standard library code. In resource-constrained * systems, this should be defined to something less resource-consuming. */ #ifndef LWIP_PLATFORM_DIAG @@ -83,9 +83,9 @@ #include #endif -/** Platform specific assertion handling.\n +/** Platform specific assertion handling.
* Note the default implementation pulls in printf, fflush and abort, which may - * in turn pull in a lot of standard libary code. In resource-constrained + * in turn pull in a lot of standard library code. In resource-constrained * systems, this should be defined to something less resource-consuming. */ #ifndef LWIP_PLATFORM_ASSERT @@ -261,10 +261,10 @@ typedef int ssize_t; * its start address using LWIP_MEM_ALIGN. * You can declare your own version here e.g. to enforce alignment without adding * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement - * requirements.\n - * e.g. if you use gcc and need 32 bit alignment:\n - * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n - * or more portable:\n + * requirements.
+ * e.g. if you use gcc and need 32 bit alignment:
+ * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))
+ * or more portable:
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)] */ #ifndef LWIP_DECLARE_MEMORY_ALIGNED @@ -299,8 +299,8 @@ extern "C" { #endif /** Packed structs support. - * Placed BEFORE declaration of a packed struct.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Placed BEFORE declaration of a packed struct.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_BEGIN @@ -308,8 +308,8 @@ extern "C" { #endif /* PACK_STRUCT_BEGIN */ /** Packed structs support. - * Placed AFTER declaration of a packed struct.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Placed AFTER declaration of a packed struct.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_END @@ -317,8 +317,8 @@ extern "C" { #endif /* PACK_STRUCT_END */ /** Packed structs support. - * Placed between end of declaration of a packed struct and trailing semicolon.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Placed between end of declaration of a packed struct and trailing semicolon.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_STRUCT @@ -330,8 +330,8 @@ extern "C" { #endif /* PACK_STRUCT_STRUCT */ /** Packed structs support. - * Wraps u32_t and u16_t members.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Wraps u32_t and u16_t members.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_FIELD @@ -339,8 +339,8 @@ extern "C" { #endif /* PACK_STRUCT_FIELD */ /** Packed structs support. - * Wraps u8_t members, where some compilers warn that packing is not necessary.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Wraps u8_t members, where some compilers warn that packing is not necessary.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_FLD_8 @@ -348,20 +348,20 @@ extern "C" { #endif /* PACK_STRUCT_FLD_8 */ /** Packed structs support. - * Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.
+ * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifndef PACK_STRUCT_FLD_S #define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) #endif /* PACK_STRUCT_FLD_S */ -/** PACK_STRUCT_USE_INCLUDES==1: Packed structs support using \#include files before and after struct to be packed.\n - * The file included BEFORE the struct is "arch/bpstruct.h".\n - * The file included AFTER the struct is "arch/epstruct.h".\n +/** PACK_STRUCT_USE_INCLUDES==1: Packed structs support using \#include files before and after struct to be packed.
+ * The file included BEFORE the struct is "arch/bpstruct.h".
+ * The file included AFTER the struct is "arch/epstruct.h".
* This can be used to implement struct packing on MS Visual C compilers, see - * the Win32 port in the lwIP contrib repository for reference. - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * the Win32 port in the lwIP/contrib subdir for reference. + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. */ #ifdef __DOXYGEN__ @@ -382,6 +382,15 @@ extern "C" { #define LWIP_PROVIDE_ERRNO #endif +/* Use a special, reproducible version of rand() for fuzz tests? */ +#ifdef LWIP_RAND_FOR_FUZZ +#ifdef LWIP_RAND +#undef LWIP_RAND +#endif +u32_t lwip_fuzz_rand(void); +#define LWIP_RAND() lwip_fuzz_rand() +#endif + /** * @} */ diff --git a/src/lwip/autoip.h b/src/lwip/autoip.h index 1d85bcc..b3f9feb 100644 --- a/src/lwip/autoip.h +++ b/src/lwip/autoip.h @@ -48,15 +48,12 @@ #include "lwip/netif.h" /* #include "lwip/udp.h" */ #include "lwip/etharp.h" +#include "lwip/acd.h" #ifdef __cplusplus extern "C" { #endif -/** AutoIP Timing */ -#define AUTOIP_TMR_INTERVAL 100 -#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) - /** AutoIP state information per netif */ struct autoip { @@ -64,26 +61,20 @@ struct autoip ip4_addr_t llipaddr; /** current AutoIP state machine state */ u8_t state; - /** sent number of probes or announces, dependent on state */ - u8_t sent_num; - /** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ - u16_t ttw; - /** ticks until a conflict can be solved by defending */ - u8_t lastconflict; /** total number of probed/used Link Local IP-Addresses */ u8_t tried_llipaddr; + /** acd struct */ + struct acd acd; }; void autoip_set_struct(struct netif *netif, struct autoip *autoip); -/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ -#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) +void autoip_remove_struct(struct netif *netif); err_t autoip_start(struct netif *netif); err_t autoip_stop(struct netif *netif); -void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); -void autoip_tmr(void); -void autoip_network_changed(struct netif *netif); -u8_t autoip_supplied_address(const struct netif *netif); +void autoip_network_changed_link_up(struct netif *netif); +void autoip_network_changed_link_down(struct netif *netif); +u8_t autoip_supplied_address(struct netif *netif); /* for lwIP internal use by ip4.c */ u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); diff --git a/src/lwip/debug.h b/src/lwip/debug.h index 579fd24..0ec7e76 100644 --- a/src/lwip/debug.h +++ b/src/lwip/debug.h @@ -140,11 +140,12 @@ #endif #ifdef LWIP_DEBUG -#define LWIP_DEBUGF(debug, message) do { \ - if ( \ - ((debug) & LWIP_DBG_ON) && \ +#define LWIP_DEBUG_ENABLED(debug) (((debug) & LWIP_DBG_ON) && \ ((debug) & LWIP_DBG_TYPES_ON) && \ - ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) + +#define LWIP_DEBUGF(debug, message) do { \ + if (LWIP_DEBUG_ENABLED(debug)) { \ LWIP_PLATFORM_DIAG(message); \ if ((debug) & LWIP_DBG_HALT) { \ while(1); \ @@ -153,6 +154,7 @@ } while(0) #else /* LWIP_DEBUG */ +#define LWIP_DEBUG_ENABLED(debug) 0 #define LWIP_DEBUGF(debug, message) #endif /* LWIP_DEBUG */ diff --git a/src/lwip/def.h b/src/lwip/def.h index dfb266d..fd7c6a2 100644 --- a/src/lwip/def.h +++ b/src/lwip/def.h @@ -144,6 +144,20 @@ int lwip_stricmp(const char* str1, const char* str2); /* This can be #defined to strnstr() depending on your platform */ char* lwip_strnstr(const char* buffer, const char* token, size_t n); #endif +#ifndef lwip_strnistr +/* This can be #defined to strnistr() depending on your platform */ +char* lwip_strnistr(const char* buffer, const char* token, size_t n); +#endif +#ifndef lwip_memcmp_consttime +/* This could be #defined to something existing on your platform + * The goal of this function is to compare memory with constant runtime in order to prevent + * timing attacks to various parts in the stack. + * To do that, in contrast to memcmp(), it only returns: + * 0: equal + * != 0: not equal + */ +int lwip_memcmp_consttime(const void* s1, const void* s2, size_t len); +#endif #ifdef __cplusplus } diff --git a/src/lwip/dhcp.h b/src/lwip/dhcp.h index c78aa0b..b413fa6 100644 --- a/src/lwip/dhcp.h +++ b/src/lwip/dhcp.h @@ -45,12 +45,25 @@ #include "lwip/netif.h" #include "lwip/udp.h" +#if LWIP_DHCP_DOES_ACD_CHECK +#include "lwip/acd.h" +#endif /* LWIP_DHCP_DOES_ACD_CHECK */ + #ifdef __cplusplus extern "C" { #endif +/** Define DHCP_TIMEOUT_SIZE_T in opt.h if you want use a different integer than u16_t. + * Especially useful if DHCP_COARSE_TIMER_SECS is in smaller units, so timeouts easily reach UINT16_MAX and more */ +#ifdef DHCP_TIMEOUT_SIZE_T +typedef DHCP_TIMEOUT_SIZE_T dhcp_timeout_t; +#else /* DHCP_TIMEOUT_SIZE_T */ +typedef u16_t dhcp_timeout_t; +#endif /* DHCP_TIMEOUT_SIZE_T*/ /** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#ifndef DHCP_COARSE_TIMER_SECS #define DHCP_COARSE_TIMER_SECS 60 +#endif /* DHCP_COARSE_TIMER_SECS */ /** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ #define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) /** period (in milliseconds) of the application calling dhcp_fine_tmr() */ @@ -58,6 +71,9 @@ extern "C" { #define DHCP_BOOT_FILE_LEN 128U +#define DHCP_FLAG_SUBNET_MASK_GIVEN 0x01 +#define DHCP_FLAG_EXTERNAL_MEM 0x02 + /* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ typedef enum { DHCP_AUTOIP_COOP_STATE_OFF = 0, @@ -74,18 +90,16 @@ struct dhcp u8_t state; /** retries of current request */ u8_t tries; -#if LWIP_DHCP_AUTOIP_COOP - u8_t autoip_coop_state; -#endif - u8_t subnet_mask_given; - - u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ - u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ - u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ - u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ - u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ - u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ - u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + /** see DHCP_FLAG_* */ + u8_t flags; + + dhcp_timeout_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + dhcp_timeout_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + dhcp_timeout_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + dhcp_timeout_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + dhcp_timeout_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + dhcp_timeout_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + dhcp_timeout_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ ip4_addr_t offered_ip_addr; ip4_addr_t offered_sn_mask; @@ -98,6 +112,10 @@ struct dhcp ip4_addr_t offered_si_addr; char boot_file_name[DHCP_BOOT_FILE_LEN]; #endif /* LWIP_DHCP_BOOTPFILE */ +#if LWIP_DHCP_DOES_ACD_CHECK + /** acd struct */ + struct acd acd; +#endif /* LWIP_DHCP_DOES_ACD_CHECK */ }; @@ -111,10 +129,8 @@ err_t dhcp_release(struct netif *netif); void dhcp_stop(struct netif *netif); void dhcp_release_and_stop(struct netif *netif); void dhcp_inform(struct netif *netif); -void dhcp_network_changed(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); -#endif +void dhcp_network_changed_link_up(struct netif *netif); + u8_t dhcp_supplied_address(const struct netif *netif); /* to be called every minute */ void dhcp_coarse_tmr(void); diff --git a/src/lwip/etharp.h b/src/lwip/etharp.h index 2036b24..48a1d22 100644 --- a/src/lwip/etharp.h +++ b/src/lwip/etharp.h @@ -88,6 +88,11 @@ err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); #define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) void etharp_cleanup_netif(struct netif *netif); +#if LWIP_ACD +err_t etharp_acd_probe(struct netif *netif, const ip4_addr_t *ipaddr); +err_t etharp_acd_announce(struct netif *netif, const ip4_addr_t *ipaddr); +#endif /* LWIP_ACD */ + #if ETHARP_SUPPORT_STATIC_ENTRIES err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); diff --git a/src/lwip/igmp.h b/src/lwip/igmp.h index ffd80e6..0a16db0 100644 --- a/src/lwip/igmp.h +++ b/src/lwip/igmp.h @@ -99,7 +99,7 @@ err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); void igmp_tmr(void); -/** @ingroup igmp +/** @ingroup igmp * Get list head of IGMP groups for netif. * Note: The allsystems group IP is contained in the list as first entry. * @see @ref netif_set_igmp_mac_filter() diff --git a/src/lwip/inet.h b/src/lwip/inet.h index 2982a0f..0970885 100644 --- a/src/lwip/inet.h +++ b/src/lwip/inet.h @@ -41,6 +41,11 @@ #define LWIP_HDR_INET_H #include "lwip/opt.h" + +#if LWIP_SOCKET_EXTERNAL_HEADERS +#include LWIP_SOCKET_EXTERNAL_HEADER_INET_H +#else /* LWIP_SOCKET_EXTERNAL_HEADERS */ + #include "lwip/def.h" #include "lwip/ip_addr.h" #include "lwip/ip6_addr.h" @@ -120,6 +125,18 @@ extern const struct in6_addr in6addr_any; #define IN_LOOPBACKNET IP_LOOPBACKNET +#define IN6_IS_ADDR_UNSPECIFIED(a) ip6_addr_isany((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_LOOPBACK(a) ip6_addr_isloopback((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MULTICAST(a) ip6_addr_ismulticast((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_LINKLOCAL(a) ip6_addr_islinklocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_SITELOCAL(a) ip6_addr_issitelocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_V4MAPPED(a) ip6_addr_isipv4mappedipv6((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_V4COMPAT(a) ip6_addr_isipv4compat((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MC_NODELOCAL(a) ip6_addr_ismulticast_iflocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MC_LINKLOCAL(a) ip6_addr_ismulticast_linklocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MC_SITELOCAL(a) ip6_addr_ismulticast_sitelocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MC_ORGLOCAL(a) ip6_addr_ismulticast_orglocal((ip6_addr_t*)(a)) +#define IN6_IS_ADDR_MC_GLOBAL(a) ip6_addr_ismulticast_global((ip6_addr_t*)(a)) #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX @@ -166,4 +183,6 @@ extern const struct in6_addr in6addr_any; } #endif +#endif /* LWIP_SOCKET_EXTERNAL_HEADERS */ + #endif /* LWIP_HDR_INET_H */ diff --git a/src/lwip/inet_chksum.h b/src/lwip/inet_chksum.h index 76893ef..33296d2 100644 --- a/src/lwip/inet_chksum.h +++ b/src/lwip/inet_chksum.h @@ -102,4 +102,3 @@ u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, #endif #endif /* LWIP_HDR_INET_H */ - diff --git a/src/lwip/init.h b/src/lwip/init.h index 6cabfc8..f579da4 100644 --- a/src/lwip/init.h +++ b/src/lwip/init.h @@ -52,9 +52,9 @@ extern "C" { /** X.x.x: Major version of the stack */ #define LWIP_VERSION_MAJOR 2 /** x.X.x: Minor version of the stack */ -#define LWIP_VERSION_MINOR 1 +#define LWIP_VERSION_MINOR 2 /** x.x.X: Revision of the stack */ -#define LWIP_VERSION_REVISION 3 +#define LWIP_VERSION_REVISION 1 /** For release candidates, this is set to 1..254 * For official releases, this is set to 255 (LWIP_RC_RELEASE) * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ diff --git a/src/lwip/ip.h b/src/lwip/ip.h index 653c3b2..668d831 100644 --- a/src/lwip/ip.h +++ b/src/lwip/ip.h @@ -93,6 +93,17 @@ struct ip_pcb { IP_PCB; }; +#if LWIP_VLAN_PCP +#define pcb_has_tci(pcb) ((pcb)->netif_hints.tci >= 0) +#define pcb_tci_get(pcb) ((pcb)->netif_hints.tci) +#define pcb_tci_clear(pcb) do { (pcb)->netif_hints.tci = -1; } while(0) +#define pcb_tci_set(pcb, tci_val) do { (pcb)->netif_hints.tci = (tci_val) & 0xffff; } while(0) +#define pcb_tci_set_pcp_dei_vid(pcb, pcp, dei, vid) pcb_tci_set(pcb, (((pcp) & 7) << 13) | (((dei) & 1) << 12) | ((vid) & 0xFFF)) +#define pcb_tci_init(pcb) pcb_tci_clear(pcb) +#else +#define pcb_tci_init(pcb) +#endif + /* * Option flags per-socket. These are the same like SO_XXX in sockets.h */ @@ -326,5 +337,3 @@ err_t ip_input(struct pbuf *p, struct netif *inp); #endif #endif /* LWIP_HDR_IP_H */ - - diff --git a/src/lwip/ip4.h b/src/lwip/ip4.h index fd35a33..4d7228d 100644 --- a/src/lwip/ip4.h +++ b/src/lwip/ip4.h @@ -107,5 +107,3 @@ void ip4_debug_print(struct pbuf *p); #endif /* LWIP_IPV4 */ #endif /* LWIP_HDR_IP_H */ - - diff --git a/src/lwip/ip4_addr.h b/src/lwip/ip4_addr.h index f244c4f..9fd8a0a 100644 --- a/src/lwip/ip4_addr.h +++ b/src/lwip/ip4_addr.h @@ -130,6 +130,11 @@ struct netif; /** Get the network address by combining host address with netmask */ #define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) +/** + * Determine if two address are on the same network. + * @deprecated Renamed to @ref ip4_addr_net_eq + */ +#define ip4_addr_netcmp(addr1, addr2, mask) ip4_addr_net_eq(addr1, addr2, mask) /** * Determine if two address are on the same network. * @@ -138,11 +143,15 @@ struct netif; * @arg mask network identifier mask * @return !0 if the network identifiers of both address match */ -#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ +#define ip4_addr_net_eq(addr1, addr2, mask) (((addr1)->addr & \ (mask)->addr) == \ ((addr2)->addr & \ (mask)->addr)) -#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) +/** + * @deprecated Renamed to ip4_addr_eq + */ +#define ip4_addr_cmp(addr1, addr2) ip4_addr_eq(addr1, addr2) +#define ip4_addr_eq(addr1, addr2) ((addr1)->addr == (addr2)->addr) #define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) #define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) diff --git a/src/lwip/ip6_addr.h b/src/lwip/ip6_addr.h index 29c2a34..5937fed 100644 --- a/src/lwip/ip6_addr.h +++ b/src/lwip/ip6_addr.h @@ -146,10 +146,17 @@ typedef struct ip6_addr ip6_addr_t; ip6_addr_set_zone((dest), (src) == NULL ? IP6_NO_ZONE : ip6_addr_zone(src));}while(0) +/** @deprecated Renamed to @ref ip6_addr_net_zoneless_eq */ +#define ip6_addr_netcmp_zoneless(addr1, addr2) ip6_addr_net_zoneless_eq(addr1, addr2) /** Compare IPv6 networks, ignoring zone information. To be used sparingly! */ -#define ip6_addr_netcmp_zoneless(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ +#define ip6_addr_net_zoneless_eq(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ ((addr1)->addr[1] == (addr2)->addr[1])) +/** + * Determine if two IPv6 address are on the same network. + * @deprecated Renamed to @ref ip6_addr_net_eq + */ +#define ip6_addr_netcmp(addr1, addr2) ip6_addr_net_eq(addr1, addr2) /** * Determine if two IPv6 address are on the same network. * @@ -157,18 +164,23 @@ typedef struct ip6_addr ip6_addr_t; * @param addr2 IPv6 address 2 * @return 1 if the network identifiers of both address match, 0 if not */ -#define ip6_addr_netcmp(addr1, addr2) (ip6_addr_netcmp_zoneless((addr1), (addr2)) && \ - ip6_addr_cmp_zone((addr1), (addr2))) +#define ip6_addr_net_eq(addr1, addr2) (ip6_addr_net_zoneless_eq((addr1), (addr2)) && \ + ip6_addr_zone_eq((addr1), (addr2))) -/* Exact-host comparison *after* ip6_addr_netcmp() succeeded, for efficiency. */ -#define ip6_addr_nethostcmp(addr1, addr2) (((addr1)->addr[2] == (addr2)->addr[2]) && \ +#define ip6_addr_nethostcmp(addr1, addr2) ip6_addr_nethost_eq(addr1, addr2) +/* Exact-host comparison *after* ip6_addr_net_eq() succeeded, for efficiency. */ +#define ip6_addr_nethost_eq(addr1, addr2) (((addr1)->addr[2] == (addr2)->addr[2]) && \ ((addr1)->addr[3] == (addr2)->addr[3])) +/** @deprecated Renamed to @ref ip6_addr_zoneless_eq */ +#define ip6_addr_cmp_zoneless(addr1, addr2) ip6_addr_zoneless_eq(addr1, addr2) /** Compare IPv6 addresses, ignoring zone information. To be used sparingly! */ -#define ip6_addr_cmp_zoneless(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ +#define ip6_addr_zoneless_eq(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ ((addr1)->addr[1] == (addr2)->addr[1]) && \ ((addr1)->addr[2] == (addr2)->addr[2]) && \ ((addr1)->addr[3] == (addr2)->addr[3])) +/** @deprecated Renamed to @ref ip6_addr_eq */ +#define ip6_addr_cmp(addr1, addr2) ip6_addr_eq(addr1, addr2) /** * Determine if two IPv6 addresses are the same. In particular, the address * part of both must be the same, and the zone must be compatible. @@ -177,11 +189,13 @@ typedef struct ip6_addr ip6_addr_t; * @param addr2 IPv6 address 2 * @return 1 if the addresses are considered equal, 0 if not */ -#define ip6_addr_cmp(addr1, addr2) (ip6_addr_cmp_zoneless((addr1), (addr2)) && \ - ip6_addr_cmp_zone((addr1), (addr2))) +#define ip6_addr_eq(addr1, addr2) (ip6_addr_zoneless_eq((addr1), (addr2)) && \ + ip6_addr_zone_eq((addr1), (addr2))) +/** @deprecated Renamed to @ref ip6_addr_packed_eq */ +#define ip6_addr_cmp_packed(ip6addr, paddr, zone_idx) ip6_addr_packed_eq(ip6addr, paddr, zone_idx) /** Compare IPv6 address to packed address and zone */ -#define ip6_addr_cmp_packed(ip6addr, paddr, zone_idx) (((ip6addr)->addr[0] == (paddr)->addr[0]) && \ +#define ip6_addr_packed_eq(ip6addr, paddr, zone_idx) (((ip6addr)->addr[0] == (paddr)->addr[0]) && \ ((ip6addr)->addr[1] == (paddr)->addr[1]) && \ ((ip6addr)->addr[2] == (paddr)->addr[2]) && \ ((ip6addr)->addr[3] == (paddr)->addr[3]) && \ @@ -210,6 +224,11 @@ typedef struct ip6_addr ip6_addr_t; #define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) +#define ip6_addr_isipv4compat(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + (htonl((ip6addr)->addr[3]) > 1)) + #define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) #define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) #define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) @@ -274,7 +293,8 @@ typedef struct ip6_addr ip6_addr_t; (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id)); \ ip6_addr_clear_zone(ip6addr); }while(0) -#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) ip6_addr_solicitednode_eq(ip6addr, sn_addr) +#define ip6_addr_solicitednode_eq(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ ((ip6addr)->addr[1] == 0) && \ ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) diff --git a/src/lwip/ip6_zone.h b/src/lwip/ip6_zone.h index 525790e..834c32f 100644 --- a/src/lwip/ip6_zone.h +++ b/src/lwip/ip6_zone.h @@ -123,9 +123,11 @@ extern "C" { /** Is the zone field of the given IPv6 address equal to the given zone index? (0/1) */ #define ip6_addr_equals_zone(ip6addr, zone_idx) ((ip6addr)->zone == (zone_idx)) +/** @deprecated Renamed to @ref ip6_addr_zone_eq */ +#define ip6_addr_cmp_zone(addr1, addr2) ip6_addr_zone_eq(ip6addr1, ip6addr2) /** Are the zone fields of the given IPv6 addresses equal? (0/1) * This macro must only be used on IPv6 addresses of the same scope. */ -#define ip6_addr_cmp_zone(ip6addr1, ip6addr2) ((ip6addr1)->zone == (ip6addr2)->zone) +#define ip6_addr_zone_eq(ip6addr1, ip6addr2) ((ip6addr1)->zone == (ip6addr2)->zone) /** Symbolic constants for the 'type' parameters in some of the macros. * These exist for efficiency only, allowing the macros to avoid certain tests @@ -265,7 +267,7 @@ enum lwip_ipv6_scope_type #define ip6_addr_clear_zone(ip6addr) #define ip6_addr_copy_zone(ip6addr1, ip6addr2) #define ip6_addr_equals_zone(ip6addr, zone_idx) (1) -#define ip6_addr_cmp_zone(ip6addr1, ip6addr2) (1) +#define ip6_addr_zone_eq(ip6addr1, ip6addr2) (1) #define IPV6_CUSTOM_SCOPES 0 #define ip6_addr_has_scope(ip6addr, type) (0) #define ip6_addr_assign_zone(ip6addr, type, netif) diff --git a/src/lwip/ip_addr.h b/src/lwip/ip_addr.h index 2f97770..06454a4 100644 --- a/src/lwip/ip_addr.h +++ b/src/lwip/ip_addr.h @@ -194,39 +194,63 @@ extern const ip_addr_t ip_addr_any_type; #define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ +/** + * @ingroup ipaddr + * @deprecated Renamed to @ref ip_addr_net_eq + */ +#define ip_addr_netcmp(addr1, addr2, mask) ip_addr_net_eq((addr1), (addr2), (mask)) +/** @ingroup ipaddr + * Check if two ip addresses are share the same network, for a specific netmask. */ +#define ip_addr_net_eq(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ 0 : \ - ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) -/** @ingroup ipaddr */ -#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ - ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ - ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) -/** @ingroup ipaddr */ -#define ip_addr_cmp_zoneless(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ - ip6_addr_cmp_zoneless(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ - ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) -/** @ingroup ipaddr */ + ip4_addr_net_eq(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) +/** + * @ingroup ipaddr + * @deprecated Renamed to @ref ip_addr_eq + */ +#define ip_addr_cmp(addr1, addr2) ip_addr_eq((addr1), (addr2)) +/** @ingroup ipaddr + * Check if two ip addresses are equal. */ +#define ip_addr_eq(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_eq(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_eq(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +/** + * @ingroup ipaddr + * @deprecated Renamed to @ref ip_addr_zoneless_eq + */ +#define ip_addr_cmp_zoneless(addr1, addr2) ip_addr_zoneless_eq((addr1), (addr2)) +/** @ingroup ipaddr + * Check if two ip addresses are equal, ignoring the zone. */ +#define ip_addr_zoneless_eq(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_zoneless_eq(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_eq(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +/** @ingroup ipaddr + * Check if an ip address is the 'any' address. */ #define ip_addr_isany(ipaddr) (((ipaddr) == NULL) ? 1 : ((IP_IS_V6(ipaddr)) ? \ ip6_addr_isany(ip_2_ip6(ipaddr)) : \ ip4_addr_isany(ip_2_ip4(ipaddr)))) -/** @ingroup ipaddr */ +/** @ingroup ipaddr + * Check if an ip address is the 'any' address, by value. */ #define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) -/** @ingroup ipaddr */ +/** @ingroup ipaddr + * Check if an ip address is a broadcast address. */ #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ 0 : \ ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -/** @ingroup ipaddr */ +/** @ingroup ipaddr + * Check inf an ip address is a multicast address. */ #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ +/** @ingroup ipaddr + * Check inf an ip address is a loopback address. */ #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ ip4_addr_isloopback(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ +/** @ingroup ipaddr + * Check inf an ip address is a link-local address. */ #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ ip4_addr_islinklocal(ip_2_ip4(ipaddr))) @@ -295,8 +319,10 @@ typedef ip4_addr_t ip_addr_t; #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) -#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_net_eq(addr1, addr2, mask) +#define ip_addr_net_eq(addr1, addr2, mask) ip4_addr_net_eq(addr1, addr2, mask) +#define ip_addr_cmp(addr1, addr2) ip4_addr_eq(addr1, addr2) +#define ip_addr_eq(addr1, addr2) ip4_addr_eq(addr1, addr2) #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) @@ -343,8 +369,11 @@ typedef ip6_addr_t ip_addr_t; #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) #define ip_addr_netcmp(addr1, addr2, mask) 0 -#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) -#define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) +#define ip_addr_net_eq(addr1, addr2, mask) 0 +#define ip_addr_cmp(addr1, addr2) ip6_addr_eq(addr1, addr2) +#define ip_addr_eq(addr1, addr2) ip6_addr_eq(addr1, addr2) +#define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_zoneless_eq(addr1, addr2) +#define ip_addr_zoneless_eq(addr1, addr2) ip6_addr_zoneless_eq(addr1, addr2) #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) @@ -404,7 +433,7 @@ extern const ip_addr_t ip_addr_broadcast; extern const ip_addr_t ip6_addr_any; -/** +/** * @ingroup ip6addr * IP6_ADDR_ANY can be used as a fixed ip_addr_t * for the IPv6 wildcard address @@ -424,8 +453,9 @@ extern const ip_addr_t ip6_addr_any; #endif +/** @ingroup ipaddr + * Macro representing the 'any' address. */ #if LWIP_IPV4 && LWIP_IPV6 -/** @ingroup ipaddr */ #define IP_ANY_TYPE (&ip_addr_any_type) #else #define IP_ANY_TYPE IP_ADDR_ANY diff --git a/src/lwip/mem.h b/src/lwip/mem.h index ff208d2..6819ee4 100644 --- a/src/lwip/mem.h +++ b/src/lwip/mem.h @@ -43,7 +43,7 @@ extern "C" { #endif -#if MEM_LIBC_MALLOC +#if MEM_CUSTOM_ALLOCATOR #include "lwip/arch.h" diff --git a/src/lwip/mld6.h b/src/lwip/mld6.h index 7fa0797..2764fdd 100644 --- a/src/lwip/mld6.h +++ b/src/lwip/mld6.h @@ -84,7 +84,7 @@ err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); /** @ingroup mld6 * Get list head of MLD6 groups for netif. - * Note: The allnodes group IP is NOT in the list, since it must always + * Note: The allnodes group IP is NOT in the list, since it must always * be received for correct IPv6 operation. * @see @ref netif_set_mld_mac_filter() */ diff --git a/src/lwip/netif.h b/src/lwip/netif.h index 9a16ded..0cde2c2 100644 --- a/src/lwip/netif.h +++ b/src/lwip/netif.h @@ -119,6 +119,9 @@ enum lwip_internal_netif_client_data_index #if LWIP_AUTOIP LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, #endif +#if LWIP_ACD + LWIP_NETIF_CLIENT_DATA_INDEX_ACD, +#endif #if LWIP_IGMP LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, #endif @@ -245,14 +248,20 @@ typedef u8_t netif_addr_idx_t; #define NETIF_ADDR_IDX_MAX 0x7F #endif +#if LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP + #define LWIP_NETIF_USE_HINTS 1 + struct netif_hint { #if LWIP_NETIF_HWADDRHINT -#define LWIP_NETIF_USE_HINTS 1 -struct netif_hint { - netif_addr_idx_t addr_hint; -}; -#else /* LWIP_NETIF_HWADDRHINT */ -#define LWIP_NETIF_USE_HINTS 0 -#endif /* LWIP_NETIF_HWADDRHINT */ + u8_t addr_hint; +#endif +#if LWIP_VLAN_PCP + /** VLAN hader is set if this is >= 0 (but must be <= 0xFFFF) */ + s32_t tci; +#endif + }; +#else /* LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP */ + #define LWIP_NETIF_USE_HINTS 0 +#endif /* LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP*/ /** Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization @@ -345,7 +354,7 @@ struct netif { u8_t flags; /** descriptive abbreviation */ char name[2]; - /** number of this interface. Used for @ref if_api and @ref netifapi_netif, + /** number of this interface. Used for @ref if_api and @ref netifapi_netif, * as well as for IPv6 zones */ u8_t num; #if LWIP_IPV6_AUTOCONFIG @@ -376,6 +385,9 @@ struct netif { filter table of the ethernet MAC. */ netif_mld_mac_filter_fn mld_mac_filter; #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_ACD + struct acd *acd_list; +#endif /* LWIP_ACD */ #if LWIP_NETIF_USE_HINTS struct netif_hint *hints; #endif /* LWIP_NETIF_USE_HINTS */ @@ -396,8 +408,10 @@ struct netif { #if LWIP_CHECKSUM_CTRL_PER_NETIF #define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ (netif)->chksum_flags = chksumflags; } while(0) -#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) +#define NETIF_CHECKSUM_ENABLED(netif, chksumflag) (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if NETIF_CHECKSUM_ENABLED(netif, chksumflag) #else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define NETIF_CHECKSUM_ENABLED(netif, chksumflag) 0 #define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) #define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ @@ -488,14 +502,18 @@ void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_ #endif /* LWIP_NETIF_HOSTNAME */ #if LWIP_IGMP -/** @ingroup netif */ +/** @ingroup netif + * Set igmp mac filter function for a netif. */ #define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +/** Get the igmp mac filter function for a netif. */ #define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) #endif /* LWIP_IGMP */ #if LWIP_IPV6 && LWIP_IPV6_MLD -/** @ingroup netif */ +/** @ingroup netif + * Set mld mac filter function for a netif. */ #define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) +/** Get the mld mac filter function for a netif. */ #define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) #define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ @@ -575,8 +593,8 @@ typedef u16_t netif_nsc_reason_t; #define LWIP_NSC_NETIF_REMOVED 0x0002 /** link changed */ #define LWIP_NSC_LINK_CHANGED 0x0004 -/** netif administrative status changed.\n - * up is called AFTER netif is set up.\n +/** netif administrative status changed.
+ * up is called AFTER netif is set up.
* down is called BEFORE the netif is actually set down. */ #define LWIP_NSC_STATUS_CHANGED 0x0008 /** IPv4 address has changed */ @@ -591,6 +609,8 @@ typedef u16_t netif_nsc_reason_t; #define LWIP_NSC_IPV6_SET 0x0100 /** IPv6 address state has changed */ #define LWIP_NSC_IPV6_ADDR_STATE_CHANGED 0x0200 +/** IPv4 settings: valid address set, application may start to communicate */ +#define LWIP_NSC_IPV4_ADDR_VALID 0x0400 /** @ingroup netif * Argument supplied to netif_ext_callback_fn. @@ -666,6 +686,11 @@ void netif_invoke_ext_callback(struct netif* netif, netif_nsc_reason_t reason, c #define netif_invoke_ext_callback(netif, reason, args) #endif +#if LWIP_TESTMODE && LWIP_HAVE_LOOPIF +struct netif* netif_get_loopif(void); +#endif + + #ifdef __cplusplus } #endif diff --git a/src/lwip/opt.h b/src/lwip/opt.h index d8c82d1..2573285 100644 --- a/src/lwip/opt.h +++ b/src/lwip/opt.h @@ -227,14 +227,7 @@ #define LWIP_ASSERT_CORE_LOCKED() #endif -/** - * Called as first thing in the lwIP TCPIP thread. Can be used in conjunction - * with @ref LWIP_ASSERT_CORE_LOCKED to check core locking. - * @see @ref multithreading - */ -#if !defined LWIP_MARK_TCPIP_THREAD || defined __DOXYGEN__ -#define LWIP_MARK_TCPIP_THREAD() -#endif + /** * @} */ @@ -252,10 +245,28 @@ /** * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library * instead of the lwip internal allocator. Can save code size if you - * already use it. + * already use it. Specialized case of MEM_CUSTOM_ALLOCATOR. + * @see MEM_CUSTOM_ALLOCATOR */ #if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ #define MEM_LIBC_MALLOC 0 +#elif MEM_LIBC_MALLOC +#define MEM_CUSTOM_ALLOCATOR 1 +#define MEM_CUSTOM_FREE free +#define MEM_CUSTOM_MALLOC malloc +#define MEM_CUSTOM_CALLOC calloc +#endif + +/** + * MEM_CUSTOM_ALLOCATOR==1: Use malloc/free/realloc provided by a custom + * implementation instead of the lwip internal allocator. Can save code size if + * you already use it. If enabled, you have to define those functions: + * \#define MEM_CUSTOM_FREE my_free + * \#define MEM_CUSTOM_MALLOC my_malloc + * \#define MEM_CUSTOM_CALLOC my_calloc + */ +#if !defined MEM_CUSTOM_ALLOCATOR || defined __DOXYGEN__ +#define MEM_CUSTOM_ALLOCATOR 0 #endif /** @@ -505,7 +516,7 @@ * The number of sys timeouts used by the core stack (not apps) * The default number of timeouts is calculated here for all enabled modules. */ -#define LWIP_NUM_SYS_TIMEOUT_INTERNAL (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD))) +#define LWIP_NUM_SYS_TIMEOUT_INTERNAL (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_ACD + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD + LWIP_IPV6_DHCP6))) /** * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. @@ -677,6 +688,20 @@ #define ETHARP_SUPPORT_VLAN 0 #endif +/** + * LWIP_VLAN_PCP==1: Enable outgoing VLAN tagging of frames on a per-PCB basis + * for QoS purposes. With this feature enabled, each PCB has a new variable: + * "netif_hints.tci" (Tag Control Identifier). + * The TCI contains three fields: VID, CFI and PCP. + * - VID is the VLAN ID, which should be set to zero. + * - The "CFI" bit is used to enable or disable VLAN tags for the PCB. + * - PCP (Priority Code Point) is a 3 bit field used for Ethernet level QoS. + * See pcb_tci_*() functions to get/set/clear this. + */ +#ifndef LWIP_VLAN_PCP +#define LWIP_VLAN_PCP 0 +#endif + /** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled */ #if !defined LWIP_ETHERNET || defined __DOXYGEN__ @@ -924,10 +949,10 @@ #endif /* !LWIP_IPV4 */ /** - * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + * LWIP_DHCP_DOES_ACD_CHECK==1: Perform address conflict detection on the dhcp address. */ -#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ -#define DHCP_DOES_ARP_CHECK (LWIP_DHCP && LWIP_ARP) +#if !defined LWIP_DHCP_DOES_ACD_CHECK || defined __DOXYGEN__ +#define LWIP_DHCP_DOES_ACD_CHECK LWIP_DHCP #endif /** @@ -961,6 +986,14 @@ #if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ #define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS #endif + +/** LWIP_DHCP_DISCOVER_ADD_HOSTNAME: Set to 0 to not include hostname opt in discover packets. + * If the hostname is not set in the DISCOVER packet, then some servers might issue an OFFER with hostname + * configured and consequently reject the REQUEST with any other hostname. + */ +#if !defined LWIP_DHCP_DISCOVER_ADD_HOSTNAME || defined __DOXYGEN__ +#define LWIP_DHCP_DISCOVER_ADD_HOSTNAME 1 +#endif /* LWIP_DHCP_DISCOVER_ADD_HOSTNAME */ /** * @} */ @@ -1009,6 +1042,31 @@ * @} */ +/* + ------------------------------------ + ----------- ACD options ------------ + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_acd ACD + * @ingroup lwip_opts_ipv4 + * @{ + */ + /** + * LWIP_ACD==1: Enable ACD module. ACD module is needed when using AUTOIP. + */ +#if !defined LWIP_ACD || defined __DOXYGEN__ +#define LWIP_ACD (LWIP_AUTOIP || LWIP_DHCP_DOES_ACD_CHECK) +#endif +#if !LWIP_IPV4 +/* disable ACD when IPv4 is disabled */ +#undef LWIP_ACD +#define LWIP_ACD 0 +#endif /* !LWIP_IPV4 */ +/** + * @} + */ + /* ---------------------------------- ----- SNMP MIB2 support ----- @@ -1141,7 +1199,9 @@ * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} * * Instead, you can also use an external function: - * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) + * \#define DNS_LOOKUP_LOCAL_EXTERN(name, namelen, addr, dns_addrtype) my_lookup_function(name, namelen, addr, dns_addrtype) + * with function signature: + * extern err_t my_lookup_function(const char *name, size_t namelen, ip_addr_t *addr, u8_t dns_addrtype) * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). */ #if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ @@ -1305,6 +1365,15 @@ #define TCP_CALCULATE_EFF_SEND_MSS 1 #endif +/** + * LWIP_TCP_RTO_TIME: Initial TCP retransmission timeout (ms). + * This defaults to 3 seconds as traditionally defined in the TCP protocol. + * For improving timely recovery on faster networks, this value could + * be lowered down to 1 second (RFC 6298) + */ +#if !defined LWIP_TCP_RTO_TIME || defined __DOXYGEN__ +#define LWIP_TCP_RTO_TIME 3000 +#endif /** * TCP_SND_BUF: TCP sender buffer space (bytes). @@ -1523,13 +1592,13 @@ * link level header. The default is 14, the standard value for * Ethernet. */ -#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ -#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ -#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) -#else /* LWIP_HOOK_VLAN_SET */ -#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) -#endif /* LWIP_HOOK_VLAN_SET */ -#endif + #if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ +#if (defined LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP) && !defined __DOXYGEN__ + #define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */ + #define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */ + #endif /** * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated @@ -1559,10 +1628,22 @@ /** * LWIP_PBUF_CUSTOM_DATA: Store private data on pbufs (e.g. timestamps) * This extends struct pbuf so user can store custom data on every pbuf. + * e.g.: + * \#define LWIP_PBUF_CUSTOM_DATA u32_t myref; */ #if !defined LWIP_PBUF_CUSTOM_DATA || defined __DOXYGEN__ #define LWIP_PBUF_CUSTOM_DATA #endif + +/** + * LWIP_PBUF_CUSTOM_DATA_INIT: Initialize private data on pbufs. + * e.g. for the above example definition: + * \#define LWIP_PBUF_CUSTOM_DATA(p) (p)->myref = 0 + */ +#if !defined LWIP_PBUF_CUSTOM_DATA_INIT || defined __DOXYGEN__ +#define LWIP_PBUF_CUSTOM_DATA_INIT(p) +#endif + /** * @} */ @@ -1609,7 +1690,7 @@ #endif /** - * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function + * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function * for several netif related event that supports multiple subscribers. * @see netif_ext_status_callback */ @@ -1977,6 +2058,17 @@ #define LWIP_SOCKET_OFFSET 0 #endif +/** + * LWIP_SOCKET_EXTERNAL_HEADERS==1: Use external headers instead of sockets.h + * and inet.h. In this case, user must provide its own headers by setting the + * values for LWIP_SOCKET_EXTERNAL_HEADER_SOCKETS_H and + * LWIP_SOCKET_EXTERNAL_HEADER_INET_H to appropriate include file names and the + * whole content of the default sockets.h and inet.h is skipped. + */ +#if !defined LWIP_SOCKET_EXTERNAL_HEADERS || defined __DOXYGEN__ +#define LWIP_SOCKET_EXTERNAL_HEADERS 0 +#endif + /** * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set @@ -2176,7 +2268,7 @@ * MEM_STATS==1: Enable mem.c stats. */ #if !defined MEM_STATS || defined __DOXYGEN__ -#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#define MEM_STATS ((MEM_CUSTOM_ALLOCATOR == 0) && (MEM_USE_POOLS == 0)) #endif /** @@ -2394,7 +2486,7 @@ * All addresses that have a scope according to the default policy (link-local * unicast addresses, interface-local and link-local multicast addresses) should * now have a zone set on them before being passed to the core API, although - * lwIP will currently attempt to select a zone on the caller's behalf when + * lwIP will currently attempt to select a zone on the caller's behalf when * necessary. Applications that directly assign IPv6 addresses to interfaces * (which is NOT recommended) must now ensure that link-local addresses carry * the netif's zone. See the new ip6_zone.h header file for more information and @@ -2756,16 +2848,16 @@ * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), * or any other desired algorithm as a replacement. * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for - * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n + * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.
* Signature:\code{.c} * u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); * \endcode - * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n + * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations
* Arguments: * - local_ip: pointer to the local IP address of the connection * - local_port: local port number of the connection (host-byte order) * - remote_ip: pointer to the remote IP address of the connection - * - remote_port: remote port number of the connection (host-byte order)\n + * - remote_port: remote port number of the connection (host-byte order)
* Return value: * - the 32-bit Initial Sequence Number to use for the new TCP connection. */ @@ -2791,7 +2883,7 @@ * the first 'opt1len' bytes and the rest starts at 'opt2'. opt2len can * be simply calculated: 'opt2len = optlen - opt1len;' * - p: input packet, p->payload points to application data (that's why tcp hdr - * and options are passed in seperately) + * and options are passed in separately) * Return value: * - ERR_OK: continue input of this packet as normal * - != ERR_OK: drop this packet for input (don't continue input processing) @@ -3024,18 +3116,18 @@ * LWIP_HOOK_VLAN_SET: * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data * on per-netif basis to implement this callback, see @ref netif_cd. - * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n + * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.
* Signature:\code{.c} - * s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n + * s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); * \endcode * Arguments: * - netif: struct netif that the packet will be sent through * - p: struct pbuf packet to be sent * - src: source eth address * - dst: destination eth address - * - eth_type: ethernet type to packet to be sent\n - * - * + * - eth_type: ethernet type to packet to be sent
+ * + * * Return values: * - <0: Packet shall not contain VLAN header. * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. @@ -3471,6 +3563,13 @@ #define AUTOIP_DEBUG LWIP_DBG_OFF #endif +/** + * ACD_DEBUG: Enable debugging in acd.c. + */ +#if !defined ACD_DEBUG || defined __DOXYGEN__ +#define ACD_DEBUG LWIP_DBG_OFF +#endif + /** * DNS_DEBUG: Enable debugging for DNS. */ diff --git a/src/lwip/pbuf.h b/src/lwip/pbuf.h index e5daf96..5a4fc88 100644 --- a/src/lwip/pbuf.h +++ b/src/lwip/pbuf.h @@ -55,7 +55,7 @@ extern "C" { #define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) #endif -/** @ingroup pbuf +/** @ingroup pbuf * PBUF_NEEDS_COPY(p): return a boolean value indicating whether the given * pbuf needs to be copied in order to be kept around beyond the current call * stack without risking being corrupted. The default setting provides safety: diff --git a/src/lwip/priv/altcp_priv.h b/src/lwip/priv/altcp_priv.h index d1de9b1..50e6b97 100644 --- a/src/lwip/priv/altcp_priv.h +++ b/src/lwip/priv/altcp_priv.h @@ -1,6 +1,6 @@ /** * @file - * Application layered TCP connection API (to be used from TCPIP thread)\n + * Application layered TCP connection API (to be used from TCPIP thread)
* This interface mimics the tcp callback API to the application while preventing * direct linking (much like virtual functions). * This way, an application can make use of other application layer protocols diff --git a/src/lwip/priv/nd6_priv.h b/src/lwip/priv/nd6_priv.h index cc3007d..75d5f02 100644 --- a/src/lwip/priv/nd6_priv.h +++ b/src/lwip/priv/nd6_priv.h @@ -94,6 +94,7 @@ struct nd6_destination_cache_entry { ip6_addr_t destination_addr; ip6_addr_t next_hop_addr; u16_t pmtu; + u8_t cached_neighbor_idx; u32_t age; }; diff --git a/src/lwip/priv/sockets_priv.h b/src/lwip/priv/sockets_priv.h index d8f9904..c604734 100644 --- a/src/lwip/priv/sockets_priv.h +++ b/src/lwip/priv/sockets_priv.h @@ -99,7 +99,7 @@ struct lwip_sock { /** Maximum optlen used by setsockopt/getsockopt */ #define LWIP_SETGETSOCKOPT_MAXOPTLEN LWIP_MAX(16, sizeof(struct ifreq)) -/** This struct is used to pass data to the set/getsockopt_internal +/** This struct is used to pass data to the set/getsockopt_impl * functions running in tcpip_thread context (only a void* is allowed) */ struct lwip_setgetsockopt_data { /** socket index for which to change options */ diff --git a/src/lwip/priv/tcp_priv.h b/src/lwip/priv/tcp_priv.h index 72f9126..a8e87e5 100644 --- a/src/lwip/priv/tcp_priv.h +++ b/src/lwip/priv/tcp_priv.h @@ -106,14 +106,11 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb); #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) -#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) -#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) -#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) -#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +#define TCP_SEQ_LT(a,b) (((u32_t)((u32_t)(a) - (u32_t)(b)) & 0x80000000u) != 0) +#define TCP_SEQ_LEQ(a,b) (!(TCP_SEQ_LT(b,a))) +#define TCP_SEQ_GT(a,b) TCP_SEQ_LT(b,a) +#define TCP_SEQ_GEQ(a,b) TCP_SEQ_LEQ(b,a) /* is b<=a<=c? */ -#if 0 /* see bug #10548 */ -#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) -#endif #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) #ifndef TCP_TMR_INTERVAL @@ -361,7 +358,7 @@ extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; for (tcp_tmp_pcb = *(pcbs); \ tcp_tmp_pcb != NULL; \ tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + LWIP_ASSERT("TCP_REG: already registered", tcp_tmp_pcb != (npcb)); \ } \ LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ (npcb)->next = *(pcbs); \ @@ -467,6 +464,9 @@ void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); void tcp_rst(const struct tcp_pcb* pcb, u32_t seqno, u32_t ackno, const ip_addr_t *local_ip, const ip_addr_t *remote_ip, u16_t local_port, u16_t remote_port); +void tcp_rst_netif(struct netif *netif, u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); u32_t tcp_next_iss(struct tcp_pcb *pcb); diff --git a/src/lwip/priv/tcpip_priv.h b/src/lwip/priv/tcpip_priv.h index 74be634..bfa88ff 100644 --- a/src/lwip/priv/tcpip_priv.h +++ b/src/lwip/priv/tcpip_priv.h @@ -123,7 +123,8 @@ enum tcpip_msg_type { TCPIP_MSG_UNTIMEOUT, #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ TCPIP_MSG_CALLBACK, - TCPIP_MSG_CALLBACK_STATIC + TCPIP_MSG_CALLBACK_STATIC, + TCPIP_MSG_CALLBACK_STATIC_WAIT }; struct tcpip_msg { @@ -139,6 +140,11 @@ struct tcpip_msg { struct tcpip_api_call_data *arg; sys_sem_t *sem; } api_call; + struct { + tcpip_callback_fn function; + void *ctx; + sys_sem_t *sem; + } cb_wait; #endif /* LWIP_TCPIP_CORE_LOCKING */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT struct { diff --git a/src/lwip/prot/acd.h b/src/lwip/prot/acd.h new file mode 100644 index 0000000..860cae5 --- /dev/null +++ b/src/lwip/prot/acd.h @@ -0,0 +1,91 @@ +/** + * @file + * ACD protocol definitions + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * Copyright (c) 2018 Jasper Verschueren + * 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: Jasper Verschueren + * Author: Dominik Spies + */ + +#ifndef LWIP_HDR_PROT_ACD_H +#define LWIP_HDR_PROT_ACD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* RFC 5227 and RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (minimum interval between defensive ARPs) */ + +/* ACD states */ +typedef enum { + /* ACD is module is off */ + ACD_STATE_OFF, + /* Waiting before probing can be started */ + ACD_STATE_PROBE_WAIT, + /* Probing the ipaddr */ + ACD_STATE_PROBING, + /* Waiting before announcing the probed ipaddr */ + ACD_STATE_ANNOUNCE_WAIT, + /* Announcing the new ipaddr */ + ACD_STATE_ANNOUNCING, + /* Performing ongoing conflict detection with one defend within defend inferval */ + ACD_STATE_ONGOING, + /* Performing ongoing conflict detection but immediately back off and Release + * the address when a conflict occurs. This state is used for LL addresses + * that stay active even if the netif has a routable address selected. + * In such a case, we cannot defend our address */ + ACD_STATE_PASSIVE_ONGOING, + /* To many conflicts occurred, we need to wait before restarting the selection + * process */ + ACD_STATE_RATE_LIMIT +} acd_state_enum_t; + +typedef enum { + ACD_IP_OK, /* IP address is good, no conflicts found in checking state */ + ACD_RESTART_CLIENT, /* Conflict found -> the client should try again */ + ACD_DECLINE /* Decline the received IP address (rate limiting)*/ +} acd_callback_enum_t; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ACD_H */ diff --git a/src/lwip/prot/autoip.h b/src/lwip/prot/autoip.h index fd3af8a..adbb166 100644 --- a/src/lwip/prot/autoip.h +++ b/src/lwip/prot/autoip.h @@ -51,24 +51,11 @@ extern "C" { /* 169.254.254.255 */ #define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) -/* RFC 3927 Constants */ -#define PROBE_WAIT 1 /* second (initial random delay) */ -#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ -#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ -#define PROBE_NUM 3 /* (number of probe packets) */ -#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ -#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ -#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ -#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ -#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ -#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ - /* AutoIP client states */ typedef enum { - AUTOIP_STATE_OFF = 0, - AUTOIP_STATE_PROBING = 1, - AUTOIP_STATE_ANNOUNCING = 2, - AUTOIP_STATE_BOUND = 3 + AUTOIP_STATE_OFF, + AUTOIP_STATE_CHECKING, + AUTOIP_STATE_BOUND } autoip_state_enum_t; #ifdef __cplusplus diff --git a/src/lwip/prot/ethernet.h b/src/lwip/prot/ethernet.h index 309e574..d16b604 100644 --- a/src/lwip/prot/ethernet.h +++ b/src/lwip/prot/ethernet.h @@ -116,7 +116,9 @@ PACK_STRUCT_END #define LL_IP6_MULTICAST_ADDR_0 0x33 #define LL_IP6_MULTICAST_ADDR_1 0x33 -#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) +/* eth_addr_cmp is deprecated, use eth_addr_eq */ +#define eth_addr_cmp(addr1, addr2) eth_addr_eq((addr1), (addr2)) +#define eth_addr_eq(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) #ifdef __cplusplus } diff --git a/src/lwip/prot/icmp.h b/src/lwip/prot/icmp.h index 7d19385..1fe12d9 100644 --- a/src/lwip/prot/icmp.h +++ b/src/lwip/prot/icmp.h @@ -60,18 +60,13 @@ extern "C" { #ifdef PACK_STRUCT_USE_INCLUDES # include "arch/bpstruct.h" #endif -/** This is the standard ICMP header only that the u32_t data - * is split to two u16_t like ICMP echo needs it. - * This header is also used for other ICMP types that do not - * use the data part. - */ +/** The standard ICMP header (unspecified 32 bit data) */ PACK_STRUCT_BEGIN -struct icmp_echo_hdr { +struct icmp_hdr { PACK_STRUCT_FLD_8(u8_t type); PACK_STRUCT_FLD_8(u8_t code); PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); + PACK_STRUCT_FIELD(u32_t data); } PACK_STRUCT_STRUCT; PACK_STRUCT_END #ifdef PACK_STRUCT_USE_INCLUDES @@ -84,6 +79,25 @@ PACK_STRUCT_END #define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) #define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + #ifdef __cplusplus } #endif diff --git a/src/lwip/prot/ieee.h b/src/lwip/prot/ieee.h index abbb9e3..cd4d2de 100644 --- a/src/lwip/prot/ieee.h +++ b/src/lwip/prot/ieee.h @@ -53,7 +53,7 @@ enum lwip_ieee_eth_type { /** Internet protocol v4 */ ETHTYPE_IP = 0x0800U, /** Address resolution protocol */ - ETHTYPE_ARP = 0x0806U, + ETHTYPE_ARP = 0x0806U, /** Wake on lan */ ETHTYPE_WOL = 0x0842U, /** RARP */ diff --git a/src/lwip/prot/nd6.h b/src/lwip/prot/nd6.h index c270d07..a92d34d 100644 --- a/src/lwip/prot/nd6.h +++ b/src/lwip/prot/nd6.h @@ -153,6 +153,7 @@ PACK_STRUCT_END /** Link-layer address option. */ #define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) #define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#define ND6_LLADDR_OPTION_MIN_LENGTH (2) #ifdef PACK_STRUCT_USE_INCLUDES # include "arch/bpstruct.h" #endif diff --git a/src/lwip/raw.h b/src/lwip/raw.h index b129bd3..f916ff6 100644 --- a/src/lwip/raw.h +++ b/src/lwip/raw.h @@ -1,6 +1,6 @@ /** * @file - * raw API (to be used from TCPIP thread)\n + * raw API (to be used from TCPIP thread)
* See also @ref raw_raw */ diff --git a/src/lwip/sio.h b/src/lwip/sio.h index 7643e19..12d2a7e 100644 --- a/src/lwip/sio.h +++ b/src/lwip/sio.h @@ -123,7 +123,7 @@ u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); * * @note This function will block until all data can be sent. */ -u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +u32_t sio_write(sio_fd_t fd, const u8_t *data, u32_t len); #endif #ifndef sio_read_abort diff --git a/src/lwip/snmp.h b/src/lwip/snmp.h index 8704d0b..2431589 100644 --- a/src/lwip/snmp.h +++ b/src/lwip/snmp.h @@ -1,6 +1,6 @@ /** * @file - * SNMP support API for implementing netifs and statitics for MIB2 + * SNMP support API for implementing netifs and statistics for MIB2 */ /* diff --git a/src/lwip/sockets.h b/src/lwip/sockets.h index d70d36c..b6f3d52 100644 --- a/src/lwip/sockets.h +++ b/src/lwip/sockets.h @@ -43,6 +43,10 @@ #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +#if LWIP_SOCKET_EXTERNAL_HEADERS +#include LWIP_SOCKET_EXTERNAL_HEADER_SOCKETS_H +#else /* LWIP_SOCKET_EXTERNAL_HEADERS */ + #include "lwip/ip_addr.h" #include "lwip/netif.h" #include "lwip/err.h" @@ -55,6 +59,9 @@ extern "C" { #endif +/* sockaddr and pals include length fields */ +#define LWIP_SOCKET_HAVE_SA_LEN 1 + /* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED to prevent this code from redefining it. */ #if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) @@ -124,11 +131,13 @@ struct iovec { }; #endif +typedef int msg_iovlen_t; + struct msghdr { void *msg_name; socklen_t msg_namelen; struct iovec *msg_iov; - int msg_iovlen; + msg_iovlen_t msg_iovlen; void *msg_control; socklen_t msg_controllen; int msg_flags; @@ -400,7 +409,7 @@ typedef struct ipv6_mreq { * we restrict parameters to at most 128 bytes. */ #if !defined(FIONREAD) || !defined(FIONBIO) -#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOCPARM_MASK 0x7fUL /* parameters must be < 128 bytes */ #define IOC_VOID 0x20000000UL /* no parameters */ #define IOC_OUT 0x40000000UL /* copy out parameters */ #define IOC_IN 0x80000000UL /* copy in parameters */ @@ -525,6 +534,16 @@ struct timeval { }; #endif /* LWIP_TIMEVAL_PRIVATE */ +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET_EXTERNAL_HEADERS */ + +#ifdef __cplusplus +extern "C" { +#endif + #define lwip_socket_init() /* Compatibility define, no init needed. */ void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ diff --git a/src/lwip/stats.h b/src/lwip/stats.h index b570dba..8c94320 100644 --- a/src/lwip/stats.h +++ b/src/lwip/stats.h @@ -122,7 +122,7 @@ struct stats_sys { /** SNMP MIB2 stats */ struct stats_mib2 { - /* IP */ + /* IPv4 */ u32_t ipinhdrerrors; u32_t ipinaddrerrors; u32_t ipinunknownprotos; @@ -140,6 +140,9 @@ struct stats_mib2 { u32_t ipforwdatagrams; u32_t ipinreceives; + /* IPv6 */ + u32_t ip6reasmoks; + /* TCP */ u32_t tcpactiveopens; u32_t tcppassiveopens; diff --git a/src/lwip/sys.h b/src/lwip/sys.h index 168e465..4bfdb13 100644 --- a/src/lwip/sys.h +++ b/src/lwip/sys.h @@ -130,7 +130,7 @@ typedef void (*lwip_thread_fn)(void *arg); * 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. - * + * * @param mutex pointer to the mutex to create * @return ERR_OK if successful, another err_t otherwise */ @@ -205,13 +205,13 @@ void sys_sem_signal(sys_sem_t *sem); * "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. - * + * * The return value is SYS_ARCH_TIMEOUT if the semaphore wasn't signaled within * the specified time or any other value if it was signaled (with or without * waiting). * Notice that lwIP implements a function with a similar name, * sys_sem_wait(), that uses the sys_arch_sem_wait() function. - * + * * @param sem the semaphore to wait for * @param timeout timeout in milliseconds to wait (0 = wait forever) * @return SYS_ARCH_TIMEOUT on timeout, any other value on success @@ -277,7 +277,7 @@ void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ * 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. - * + * * @param mbox pointer to the mbox to create * @param size (minimum) number of messages in this mbox * @return ERR_OK if successful, another err_t otherwise @@ -287,7 +287,7 @@ err_t sys_mbox_new(sys_mbox_t *mbox, int size); * @ingroup sys_mbox * Post a message to an mbox - may not fail * -> blocks if full, only to be used from tasks NOT from ISR! - * + * * @param mbox mbox to posts the message * @param msg message to post (ATTENTION: can be NULL) */ @@ -297,7 +297,7 @@ void sys_mbox_post(sys_mbox_t *mbox, void *msg); * Try to post a message to an mbox - may fail if full. * Can be used from ISR (if the sys arch layer allows this). * Returns ERR_MEM if it is full, else, ERR_OK if the "msg" is posted. - * + * * @param mbox mbox to posts the message * @param msg message to post (ATTENTION: can be NULL) */ @@ -307,7 +307,7 @@ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); * Try to post a message to an mbox - may fail if full. * To be be used from ISR. * Returns ERR_MEM if it is full, else, ERR_OK if the "msg" is posted. - * + * * @param mbox mbox to posts the message * @param msg message to post (ATTENTION: can be NULL) */ @@ -324,10 +324,10 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg); * The return values are the same as for the sys_arch_sem_wait() function: * SYS_ARCH_TIMEOUT if there was a timeout, any other value if a messages * is received. - * + * * Note that a function with a similar name, sys_mbox_fetch(), is - * implemented by lwIP. - * + * implemented by lwIP. + * * @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 (0 = wait forever) @@ -346,7 +346,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); * 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. - * + * * @param mbox mbox to get a message from * @param msg pointer where the message is stored * @return 0 (milliseconds) if a message has been received @@ -363,7 +363,7 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); * 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. - * + * * @param mbox mbox to delete */ void sys_mbox_free(sys_mbox_t *mbox); @@ -411,7 +411,7 @@ void sys_mbox_set_invalid(sys_mbox_t *mbox); * the "stacksize" parameter. The id of the new thread is returned. Both the id * and the priority are system dependent. * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) - * + * * @param name human-readable name for the thread (used for debugging purposes) * @param thread thread-function * @param arg parameter passed to 'thread' @@ -421,6 +421,16 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, #endif /* NO_SYS */ +/** + * @ingroup lwip_opts_lock + * Called as first thing in the lwIP TCPIP thread. Can be used in conjunction + * with @ref LWIP_ASSERT_CORE_LOCKED to check core locking. + * @see @ref multithreading + */ +#if !defined LWIP_MARK_TCPIP_THREAD || defined __DOXYGEN__ +#define LWIP_MARK_TCPIP_THREAD() +#endif + /** * @ingroup sys_misc * sys_init() must be called before anything else. @@ -435,6 +445,11 @@ void sys_init(void); u32_t sys_jiffies(void); #endif +#ifdef LWIP_FUZZ_SYS_NOW +/* This offset should be added to the time 'sys_now()' returns */ +extern u32_t sys_now_offset; +#endif + /** * @ingroup sys_time * Returns the current time in milliseconds, diff --git a/src/lwip/tcp.h b/src/lwip/tcp.h index daf7599..3991fd6 100644 --- a/src/lwip/tcp.h +++ b/src/lwip/tcp.h @@ -1,6 +1,6 @@ /** * @file - * TCP API (to be used from TCPIP thread)\n + * TCP API (to be used from TCPIP thread)
* See also @ref tcp_raw */ @@ -486,9 +486,9 @@ err_t tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_add #if LWIP_TCP_PCB_NUM_EXT_ARGS u8_t tcp_ext_arg_alloc_id(void); -void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks); -void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg); -void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id); +void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, u8_t id, const struct tcp_ext_arg_callbacks * const callbacks); +void tcp_ext_arg_set(struct tcp_pcb *pcb, u8_t id, void *arg); +void *tcp_ext_arg_get(const struct tcp_pcb *pcb, u8_t id); #endif #ifdef __cplusplus diff --git a/src/lwip/tcpbase.h b/src/lwip/tcpbase.h index 0023074..018790f 100644 --- a/src/lwip/tcpbase.h +++ b/src/lwip/tcpbase.h @@ -1,6 +1,6 @@ /** * @file - * Base TCP API definitions shared by TCP and ALTCP\n + * Base TCP API definitions shared by TCP and ALTCP
* See also @ref tcp_raw */ diff --git a/src/lwip/tcpip.h b/src/lwip/tcpip.h index 0b8880a..30ce4fe 100644 --- a/src/lwip/tcpip.h +++ b/src/lwip/tcpip.h @@ -81,6 +81,7 @@ err_t tcpip_input(struct pbuf *p, struct netif *inp); err_t tcpip_try_callback(tcpip_callback_fn function, void *ctx); err_t tcpip_callback(tcpip_callback_fn function, void *ctx); +err_t tcpip_callback_wait(tcpip_callback_fn function, void *ctx); /** @ingroup lwip_os * @deprecated use tcpip_try_callback() or tcpip_callback() instead */ diff --git a/src/lwip/udp.h b/src/lwip/udp.h index b1c78e5..f1deae3 100644 --- a/src/lwip/udp.h +++ b/src/lwip/udp.h @@ -1,6 +1,6 @@ /** * @file - * UDP API (to be used from TCPIP thread)\n + * UDP API (to be used from TCPIP thread)
* See also @ref udp_raw */ diff --git a/src/netif/bridgeif.c b/src/netif/bridgeif.c index 8a97bce..2dc88fc 100644 --- a/src/netif/bridgeif.c +++ b/src/netif/bridgeif.c @@ -120,7 +120,7 @@ typedef struct bridgeif_private_s { } bridgeif_private_t; /* netif data index to get the bridge on input */ -u8_t bridgeif_netif_client_id = 0xff; +static u8_t bridgeif_netif_client_id = 0xff; /** * @ingroup bridgeif @@ -421,7 +421,7 @@ bridgeif_init(struct netif *netif) LWIP_ASSERT("bridgeif needs an input callback", (netif->input != NULL)); #if !BRIDGEIF_PORT_NETIFS_OUTPUT_DIRECT if (netif->input == tcpip_input) { - LWIP_DEBUGF(BRIDGEIF_DEBUG | LWIP_DBG_ON, ("bridgeif does not need tcpip_input, use netif_input/ethernet_input instead")); + LWIP_DEBUGF(BRIDGEIF_DEBUG | LWIP_DBG_ON, ("bridgeif does not need tcpip_input, use netif_input/ethernet_input instead\n")); } #endif diff --git a/src/netif/bridgeif_fdb.c b/src/netif/bridgeif_fdb.c index 6739fc2..2f052ec 100644 --- a/src/netif/bridgeif_fdb.c +++ b/src/netif/bridgeif_fdb.c @@ -69,7 +69,7 @@ typedef struct bridgeif_dfdb_s { * remembers known src mac addresses to know which port to send frames destined for that * mac address. * - * ATTENTION: This is meant as an example only, in real-world use, you should + * ATTENTION: This is meant as an example only, in real-world use, you should * provide a better implementation :-) */ void @@ -120,9 +120,9 @@ bridgeif_fdb_update_src(void *fdb_ptr, struct eth_addr *src_addr, u8_t port_idx) /* not found, no free entry -> flood */ } -/** +/** * @ingroup bridgeif_fdb - * Walk our list of auto-learnt fdb entries and return a port to forward or BR_FLOOD if unknown + * Walk our list of auto-learnt fdb entries and return a port to forward or BR_FLOOD if unknown */ bridgeif_portmask_t bridgeif_fdb_get_dst_ports(void *fdb_ptr, struct eth_addr *dst_addr) diff --git a/src/netif/ethernet.c b/src/netif/ethernet.c index dd171e2..db5c514 100644 --- a/src/netif/ethernet.c +++ b/src/netif/ethernet.c @@ -67,7 +67,7 @@ const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}}; * @ingroup lwip_nosys * Process received ethernet frames. Using this function instead of directly * calling ip_input and passing ARP frames through etharp in ethernetif_input, - * the ARP cache is protected from concurrent access.\n + * the ARP cache is protected from concurrent access.
* Don't call directly, pass to netif_add() and call netif->input(). * * @param p the received packet, p->payload pointing to the ethernet header @@ -96,10 +96,6 @@ ethernet_input(struct pbuf *p, struct netif *netif) goto free_and_return; } - if (p->if_idx == NETIF_NO_INDEX) { - p->if_idx = netif_get_index(netif); - } - /* points to packet payload, which starts with an Ethernet header */ ethhdr = (struct eth_hdr *)p->payload; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, @@ -143,6 +139,10 @@ ethernet_input(struct pbuf *p, struct netif *netif) netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); #endif /* LWIP_ARP_FILTER_NETIF*/ + if (p->if_idx == NETIF_NO_INDEX) { + p->if_idx = netif_get_index(netif); + } + if (ethhdr->dest.addr[0] & 1) { /* this might be a multicast or broadcast packet */ if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { @@ -179,7 +179,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ethernet_input: IPv4 packet dropped, too short (%"U16_F"/%"U16_F")\n", p->tot_len, next_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet\n")); goto free_and_return; } else { /* pass to IP layer */ @@ -196,7 +196,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ethernet_input: ARP response packet dropped, too short (%"U16_F"/%"U16_F")\n", p->tot_len, next_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet\n")); ETHARP_STATS_INC(etharp.lenerr); ETHARP_STATS_INC(etharp.drop); goto free_and_return; @@ -273,8 +273,16 @@ ethernet_output(struct netif * netif, struct pbuf * p, struct eth_hdr *ethhdr; u16_t eth_type_be = lwip_htons(eth_type); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); +#if ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP) + s32_t vlan_prio_vid; +#ifdef LWIP_HOOK_VLAN_SET + vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); +#elif LWIP_VLAN_PCP + vlan_prio_vid = -1; + if (netif->hints && (netif->hints->tci >= 0)) { + vlan_prio_vid = (u16_t)netif->hints->tci; + } +#endif if (vlan_prio_vid >= 0) { struct eth_vlan_hdr *vlanhdr; @@ -289,7 +297,7 @@ ethernet_output(struct netif * netif, struct pbuf * p, eth_type_be = PP_HTONS(ETHTYPE_VLAN); } else -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ +#endif /* ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP) */ { if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) { goto pbuf_header_failed; diff --git a/src/netif/lowpan6.c b/src/netif/lowpan6.c index 5e6f009..8eb751c 100644 --- a/src/netif/lowpan6.c +++ b/src/netif/lowpan6.c @@ -383,6 +383,7 @@ lowpan6_frag(struct netif *netif, struct pbuf *p, const struct lowpan6_link_addr #else /* LWIP_6LOWPAN_IPHC */ /* Send uncompressed IPv6 header with appropriate dispatch byte. */ lowpan6_header_len = 1; + hidden_header_len = 0; buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ #endif /* LWIP_6LOWPAN_IPHC */ @@ -604,12 +605,12 @@ lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS if (src.addr_len == 2) { - /* If source address was compressable to short_mac_addr, and dest has same subnet and - * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ + /* If source address was compressible to short_mac_addr, and dest has same subnet and + * is also compressible to 2-bytes, assume we can infer dest as a short address too. */ dest.addr_len = 2; dest.addr[0] = ((u8_t *)q->payload)[38]; dest.addr[1] = ((u8_t *)q->payload)[39]; - if ((src.addr_len == 2) && (ip6_addr_netcmp_zoneless(&ip6_hdr->src, &ip6_hdr->dest)) && + if ((src.addr_len == 2) && (ip6_addr_net_zoneless_eq(&ip6_hdr->src, &ip6_hdr->dest)) && (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); return lowpan6_frag(netif, q, &src, &dest); @@ -679,7 +680,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif) /* check for duplicate */ lrh = lowpan6_data.reass_list; while (lrh != NULL) { - uint8_t discard = 0; + u8_t discard = 0; lrh_next = lrh->next_packet; if ((lrh->sender_addr.addr_len == src.addr_len) && (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { diff --git a/src/netif/lowpan6_ble.c b/src/netif/lowpan6_ble.c index 6de0ae3..cca8bb1 100644 --- a/src/netif/lowpan6_ble.c +++ b/src/netif/lowpan6_ble.c @@ -6,7 +6,7 @@ /* * Copyright (c) 2017 Benjamin Aigner * Copyright (c) 2015 Inico Technologies Ltd. , Author: Ivan Delamer - * + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,7 @@ * OF SUCH DAMAGE. * * Author: Benjamin Aigner - * + * * Based on the original 6lowpan implementation of lwIP ( @see 6lowpan.c) */ @@ -95,19 +95,19 @@ static struct lowpan6_link_addr rfc7668_peer_addr; /** * @ingroup rfc7668if * convert BT address to EUI64 addr - * + * * This method converts a Bluetooth MAC address to an EUI64 address, * which is used within IPv6 communication - * + * * @param dst IPv6 destination space * @param src BLE MAC address source * @param public_addr If the LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS * option is set, bit 0x02 will be set if param=0 (no public addr); cleared otherwise - * + * * @see LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS */ void -ble_addr_to_eui64(uint8_t *dst, const uint8_t *src, int public_addr) +ble_addr_to_eui64(u8_t *dst, const u8_t *src, int public_addr) { /* according to RFC7668 ch 3.2.2. */ memcpy(dst, src, 3); @@ -128,15 +128,15 @@ ble_addr_to_eui64(uint8_t *dst, const uint8_t *src, int public_addr) /** * @ingroup rfc7668if * convert EUI64 address to Bluetooth MAC addr - * + * * This method converts an EUI64 address to a Bluetooth MAC address, - * + * * @param dst BLE MAC address destination * @param src IPv6 source - * + * */ void -eui64_to_ble_addr(uint8_t *dst, const uint8_t *src) +eui64_to_ble_addr(u8_t *dst, const u8_t *src) { /* according to RFC7668 ch 3.2.2. */ memcpy(dst,src,3); @@ -214,16 +214,16 @@ rfc7668_set_peer_addr_mac48(struct netif *netif, const u8_t *peer_addr, size_t p } /** Encapsulate IPv6 frames for BLE transmission - * + * * This method implements the IPv6 header compression: * *) According to RFC6282 * *) See Figure 2, contains base format of bit positions * *) Fragmentation not necessary (done at L2CAP layer of BLE) * @note Currently the pbuf allocation uses 256 bytes. If longer packets are used (possible due to MTU=1480Bytes), increase it here! - * + * * @param p Pbuf struct, containing the payload data * @param netif Output network interface. Should be of RFC7668 type - * + * * @return Same as netif->output. */ static err_t @@ -340,7 +340,7 @@ rfc7668_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) * @param p the received packet, p->payload pointing to the * IPv6 header (maybe compressed) * @param netif the network interface on which the packet was received - * + * * @return ERR_OK if everything was fine */ err_t @@ -352,7 +352,7 @@ rfc7668_input(struct pbuf * p, struct netif *netif) /* Load first header byte */ puc = (u8_t*)p->payload; - + /* no IP header compression */ if (*puc == 0x41) { LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Completed packet, removing dispatch: 0x%2x \n", *puc)); @@ -386,7 +386,7 @@ rfc7668_input(struct pbuf * p, struct netif *netif) if ((i%4)==0) { LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("\n")); } - LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("%2X ", *((uint8_t *)p->payload+i))); + LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("%2X ", *((u8_t *)p->payload+i))); } LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("\np->len: %d\n", p->len)); } @@ -398,12 +398,12 @@ rfc7668_input(struct pbuf * p, struct netif *netif) /** * @ingroup rfc7668if * Initialize the netif - * + * * No flags are used (broadcast not possible, not ethernet, ...) * The shortname for this netif is "BT" * * @param netif the network interface to be initialized as RFC7668 netif - * + * * @return ERR_OK if everything went fine */ err_t @@ -433,7 +433,7 @@ rfc7668_if_init(struct netif *netif) * @param p the received packet, p->payload pointing to the * IEEE 802.15.4 header. * @param inp the network interface on which the packet was received - * + * * @return see @ref tcpip_inpkt, same return values */ err_t diff --git a/src/netif/lowpan6_ble.h b/src/netif/lowpan6_ble.h index 01896a7..ff35fcd 100644 --- a/src/netif/lowpan6_ble.h +++ b/src/netif/lowpan6_ble.h @@ -6,7 +6,7 @@ /* * Copyright (c) 2017 Benjamin Aigner * Copyright (c) 2015 Inico Technologies Ltd. , Author: Ivan Delamer - * + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,10 +32,10 @@ * OF SUCH DAMAGE. * * Author: Benjamin Aigner - * + * * Based on the original 6lowpan implementation of lwIP ( @see 6lowpan.c) */ - + #ifndef LWIP_HDR_LOWPAN6_BLE_H #define LWIP_HDR_LOWPAN6_BLE_H @@ -66,8 +66,8 @@ err_t rfc7668_if_init(struct netif *netif); err_t tcpip_rfc7668_input(struct pbuf *p, struct netif *inp); #endif -void ble_addr_to_eui64(uint8_t *dst, const uint8_t *src, int public_addr); -void eui64_to_ble_addr(uint8_t *dst, const uint8_t *src); +void ble_addr_to_eui64(u8_t *dst, const u8_t *src, int public_addr); +void eui64_to_ble_addr(u8_t *dst, const u8_t *src); #ifdef __cplusplus } diff --git a/src/netif/lowpan6_common.c b/src/netif/lowpan6_common.c index 4db1ebb..9f50658 100644 --- a/src/netif/lowpan6_common.c +++ b/src/netif/lowpan6_common.c @@ -117,7 +117,7 @@ lowpan6_context_lookup(const ip6_addr_t *lowpan6_contexts, const ip6_addr_t *ip6 s8_t i; for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { - if (ip6_addr_netcmp(&lowpan6_contexts[i], ip6addr)) { + if (ip6_addr_net_eq(&lowpan6_contexts[i], ip6addr)) { return i; } } @@ -424,13 +424,13 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, } LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("%2X ", lowpan6_buffer[j])); } - LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("\np->len: %d", lowpan6_bufsize)); + LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("\np->len: %d\n", lowpan6_bufsize)); } #endif /* offset for inline IP headers (RFC 6282 ch3)*/ lowpan6_offset = 2; - /* if CID is set (context identifier), the context byte + /* if CID is set (context identifier), the context byte * follows immediately after the header, so other IPHC fields are @+3 */ if (lowpan6_buffer[1] & 0x80) { lowpan6_offset++; @@ -523,7 +523,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, lowpan6_offset += 2; } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 11, src compression, 0bits inline, using other headers\n")); - /* no information avalaible, using other layers, see RFC6282 ch 3.2.2 */ + /* no information available, using other layers, see RFC6282 ch 3.2.2 */ ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); ip6hdr->src.addr[1] = 0; if (src->addr_len == 2) { @@ -667,7 +667,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, /* M=0, DAC=0, determining destination address length via DAM=xx */ if ((lowpan6_buffer[1] & 0x03) == 0x00) { - LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 00, no dst compression, fetching 128bits inline")); + LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 00, no dst compression, fetching 128bits inline\n")); /* DAM=00, copy full address */ MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); lowpan6_offset += 16; diff --git a/src/netif/lowpan6_opts.h b/src/netif/lowpan6_opts.h index 17d46cd..32e5c5e 100644 --- a/src/netif/lowpan6_opts.h +++ b/src/netif/lowpan6_opts.h @@ -109,7 +109,7 @@ #define LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG LWIP_DBG_OFF #endif -/** LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS: +/** LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS: * Currently, the linux kernel driver for 6lowpan sets/clears a bit in * the address, depending on the BD address (either public or not). * Might not be RFC7668 conform, so you may select to do that (=1) or diff --git a/src/netif/ppp/auth.c b/src/netif/ppp/auth.c index c8673ad..1f27175 100644 --- a/src/netif/ppp/auth.c +++ b/src/netif/ppp/auth.c @@ -591,9 +591,9 @@ void start_link(unit) * incoming events (reply, timeout, etc.). */ if (ifunit >= 0) - ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); + ppp_notice(("Connect: %s <--> %s", ifname, ppp_devnam)); else - ppp_notice("Starting negotiation on %s", ppp_devnam); + ppp_notice(("Starting negotiation on %s", ppp_devnam)); add_fd(fd_ppp); new_phase(pcb, PPP_PHASE_ESTABLISH); @@ -634,12 +634,12 @@ void link_terminated(ppp_pcb *pcb) { #endif /* UNUSED */ if (!doing_multilink) { - ppp_notice("Connection terminated."); + ppp_notice(("Connection terminated.")); #if PPP_STATS_SUPPORT print_link_stats(); #endif /* PPP_STATS_SUPPORT */ } else - ppp_notice("Link terminated."); + ppp_notice(("Link terminated.")); lcp_lowerdown(pcb); @@ -791,7 +791,7 @@ void link_established(ppp_pcb *pcb) { || !wo->neg_upap #endif /* PAP_SUPPORT */ ) { - ppp_warn("peer refused to authenticate: terminating link"); + ppp_warn(("peer refused to authenticate: terminating link")); #if 0 /* UNUSED */ status = EXIT_PEER_AUTH_FAILED; #endif /* UNUSED */ @@ -868,7 +868,7 @@ static void network_phase(ppp_pcb *pcb) { #if 0 /* UNUSED */ /* Log calling number. */ if (*remote_number) - ppp_notice("peer from calling number %q authorized", remote_number); + ppp_notice(("peer from calling number %q authorized", remote_number)); #endif /* UNUSED */ #if PPP_NOTIFY @@ -1003,17 +1003,17 @@ void continue_networks(ppp_pcb *pcb) { * 1: Authentication succeeded. * In either case, msg points to an appropriate message and msglen to the message len. */ -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { - int secretuserlen; - int secretpasswdlen; +int auth_check_passwd(ppp_pcb *pcb, char *auser, unsigned int userlen, char *apasswd, unsigned int passwdlen, const char **msg, int *msglen) { + size_t secretuserlen; + size_t secretpasswdlen; if (pcb->settings.user && pcb->settings.passwd) { - secretuserlen = (int)strlen(pcb->settings.user); - secretpasswdlen = (int)strlen(pcb->settings.passwd); + secretuserlen = strlen(pcb->settings.user); + secretpasswdlen = strlen(pcb->settings.passwd); if (secretuserlen == userlen && secretpasswdlen == passwdlen - && !memcmp(auser, pcb->settings.user, userlen) - && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { + && !lwip_memcmp_consttime(auser, pcb->settings.user, userlen) + && !lwip_memcmp_consttime(apasswd, pcb->settings.passwd, passwdlen) ) { *msg = "Login ok"; *msglen = sizeof("Login ok")-1; return 1; @@ -1049,6 +1049,7 @@ void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char * LWIP_UNUSED_ARG(name); LWIP_UNUSED_ARG(namelen); #endif /* HAVE_MULTILINK */ + LWIP_UNUSED_ARG(prot_flavor); /* if CHAP_SUPPORT is disabled */ switch (protocol) { #if CHAP_SUPPORT @@ -1082,7 +1083,7 @@ void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char * break; #endif /* EAP_SUPPORT */ default: - ppp_warn("auth_peer_success: unknown protocol %x", protocol); + ppp_warn(("auth_peer_success: unknown protocol %x", protocol)); return; } @@ -1136,6 +1137,7 @@ void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { int bit; const char *prot = ""; + LWIP_UNUSED_ARG(prot_flavor); /* if CHAP_SUPPORT is disabled */ switch (protocol) { #if CHAP_SUPPORT @@ -1172,12 +1174,12 @@ void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { break; #endif /* EAP_SUPPORT */ default: - ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); + ppp_warn(("auth_withpeer_success: unknown protocol %x", protocol)); bit = 0; /* no break */ } - ppp_notice("%s authentication succeeded", prot); + ppp_notice(("%s authentication succeeded", prot)); /* Save the authentication method for later. */ pcb->auth_done |= bit; @@ -1300,7 +1302,7 @@ check_maxoctets(arg) break; } if (used > maxoctets) { - ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); + ppp_notice(("Traffic limit reached. Limit: %u Used: %u", maxoctets, used)); status = EXIT_TRAFFIC_LIMIT; lcp_close(pcb, "Traffic limit"); #if 0 /* UNUSED */ @@ -1338,7 +1340,7 @@ static void check_idle(void *arg) { #endif /* UNUSED */ if (tlim <= 0) { /* link is idle: shut it down. */ - ppp_notice("Terminating connection due to lack of activity."); + ppp_notice(("Terminating connection due to lack of activity.")); pcb->err_code = PPPERR_IDLETIMEOUT; lcp_close(pcb, "Link inactive"); #if 0 /* UNUSED */ @@ -1356,7 +1358,7 @@ static void check_idle(void *arg) { */ static void connect_time_expired(void *arg) { ppp_pcb *pcb = (ppp_pcb*)arg; - ppp_info("Connect time expired"); + ppp_info(("Connect time expired")); pcb->err_code = PPPERR_CONNECTTIME; lcp_close(pcb, "Connect time expired"); /* Close connection */ } @@ -1495,7 +1497,7 @@ auth_check_options() * Early check for remote number authorization. */ if (!auth_number()) { - ppp_warn("calling number %q is not authorized", remote_number); + ppp_warn(("calling number %q is not authorized", remote_number)); exit(EXIT_CNID_AUTH_FAILED); } } @@ -1609,12 +1611,12 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) ret = UPAP_AUTHNAK; f = fopen(filename, "r"); if (f == NULL) { - ppp_error("Can't open PAP password file %s: %m", filename); + ppp_error(("Can't open PAP password file %s: %m", filename)); } else { check_access(f, filename); if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { - ppp_warn("no PAP secret found for %s", user); + ppp_warn(("no PAP secret found for %s", user)); } else { /* * If the secret is "@login", it means to check @@ -1629,7 +1631,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) } } else if (session_mgmt) { if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { - ppp_warn("Peer %q failed PAP Session verification", user); + ppp_warn(("Peer %q failed PAP Session verification", user)); ret = UPAP_AUTHNAK; } } @@ -1653,7 +1655,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) * On 10'th, drop the connection. */ if (attempts++ >= 10) { - ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); + ppp_warn(("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user)); lcp_close(pcb, "login failed"); } if (attempts > 3) @@ -1902,7 +1904,7 @@ have_srp_secret(client, server, need_ip, lacks_ipp) * (We could be either client or server). */ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { - int len; + size_t len; LWIP_UNUSED_ARG(server); LWIP_UNUSED_ARG(am_server); @@ -1910,9 +1912,9 @@ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secre return 0; } - len = (int)strlen(pcb->settings.passwd); + len = strlen(pcb->settings.passwd); if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); + ppp_error(("Secret for %s on %s is too long", client, server)); len = MAXSECRETLEN; } @@ -1922,7 +1924,8 @@ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secre #if 0 /* UNUSED */ FILE *f; - int ret, len; + int ret; + size_t len; char *filename; struct wordlist *addrs, *opts; char secbuf[MAXWORDLEN]; @@ -1933,8 +1936,8 @@ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secre strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); } else if (!am_server && chap_passwd_hook) { if ( (*chap_passwd_hook)(client, secbuf) < 0) { - ppp_error("Unable to obtain CHAP password for %s on %s from plugin", - client, server); + ppp_error(("Unable to obtain CHAP password for %s on %s from plugin", + client, server)); return 0; } } else { @@ -1944,7 +1947,7 @@ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secre f = fopen(filename, "r"); if (f == NULL) { - ppp_error("Can't open chap secret file %s: %m", filename); + ppp_error(("Can't open chap secret file %s: %m", filename)); return 0; } check_access(f, filename); @@ -1964,7 +1967,7 @@ int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secre len = strlen(secbuf); if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); + ppp_error(("Secret for %s on %s is too long", client, server)); len = MAXSECRETLEN; } MEMCPY(secret, secbuf, len); @@ -2004,7 +2007,7 @@ get_srp_secret(unit, client, server, secret, am_server) fp = fopen(filename, "r"); if (fp == NULL) { - ppp_error("Can't open srp secret file %s: %m", filename); + ppp_error(("Can't open srp secret file %s: %m", filename)); return 0; } check_access(fp, filename); @@ -2098,8 +2101,8 @@ set_allowed_addrs(unit, addrs, opts) bit_count = (int) strtol (ptr_mask+1, &endp, 10); if (bit_count <= 0 || bit_count > 32) { - ppp_warn("invalid address length %v in auth. address list", - ptr_mask+1); + ppp_warn(("invalid address length %v in auth. address list", + ptr_mask+1)); continue; } bit_count = 32 - bit_count; /* # bits in host part */ @@ -2108,7 +2111,7 @@ set_allowed_addrs(unit, addrs, opts) ++endp; } if (*endp != 0) { - ppp_warn("invalid address length syntax: %v", ptr_mask+1); + ppp_warn(("invalid address length syntax: %v", ptr_mask+1)); continue; } *ptr_mask = '\0'; @@ -2141,13 +2144,13 @@ set_allowed_addrs(unit, addrs, opts) *ptr_mask = '/'; if (a == (u32_t)-1L) { - ppp_warn("unknown host %s in auth. address list", ap->word); + ppp_warn(("unknown host %s in auth. address list", ap->word)); continue; } if (offset != 0) { if (offset >= ~mask) { - ppp_warn("interface unit %d too large for subnet %v", - ifunit, ptr_word); + ppp_warn(("interface unit %d too large for subnet %v", + ifunit, ptr_word)); continue; } a = lwip_htonl((lwip_ntohl(a) & mask) + offset); @@ -2295,10 +2298,10 @@ check_access(f, filename) struct stat sbuf; if (fstat(fileno(f), &sbuf) < 0) { - ppp_warn("cannot stat secret file %s: %m", filename); + ppp_warn(("cannot stat secret file %s: %m", filename)); } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - ppp_warn("Warning - secret file %s has world and/or group access", - filename); + ppp_warn(("Warning - secret file %s has world and/or group access", + filename)); } } @@ -2408,12 +2411,12 @@ scan_authfile(f, client, server, secret, addrs, opts, filename, flags) if (word[0] == '@' && word[1] == '/') { strlcpy(atfile, word+1, sizeof(atfile)); if ((sf = fopen(atfile, "r")) == NULL) { - ppp_warn("can't open indirect secret file %s", atfile); + ppp_warn(("can't open indirect secret file %s", atfile)); continue; } check_access(sf, atfile); if (!getword(sf, word, &xxx, atfile)) { - ppp_warn("no secret in indirect secret file %s", atfile); + ppp_warn(("no secret in indirect secret file %s", atfile)); fclose(sf); continue; } diff --git a/src/netif/ppp/ccp.c b/src/netif/ppp/ccp.c index f8519eb..86ecb9f 100644 --- a/src/netif/ppp/ccp.c +++ b/src/netif/ppp/ccp.c @@ -463,10 +463,10 @@ static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { oldstate = f->state; fsm_input(f, p, len); if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { - ppp_notice("Compression disabled by peer."); + ppp_notice(("Compression disabled by peer.")); #if MPPE_SUPPORT if (go->mppe) { - ppp_error("MPPE disabled, closing LCP"); + ppp_error(("MPPE disabled, closing LCP")); lcp_close(pcb, "MPPE disabled by peer"); } #endif /* MPPE_SUPPORT */ @@ -528,7 +528,7 @@ static void ccp_protrej(ppp_pcb *pcb) { #if MPPE_SUPPORT if (go->mppe) { - ppp_error("MPPE required but peer negotiation failed"); + ppp_error(("MPPE required but peer negotiation failed")); lcp_close(pcb, "MPPE required but peer negotiation failed"); } #endif /* MPPE_SUPPORT */ @@ -589,20 +589,20 @@ static void ccp_resetci(fsm *f) { auth_mschap_bits >>= 1; } while (auth_mschap_bits); if (numbits > 1) { - ppp_error("MPPE required, but auth done in both directions."); + ppp_error(("MPPE required, but auth done in both directions.")); lcp_close(pcb, "MPPE required but not available"); return; } if (!numbits) { - ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); + ppp_error(("MPPE required, but MS-CHAP[v2] auth not performed.")); lcp_close(pcb, "MPPE required but not available"); return; } /* A plugin (eg radius) may not have obtained key material. */ if (!pcb->mppe_keys_set) { - ppp_error("MPPE required, but keys are not available. " - "Possible plugin problem?"); + ppp_error(("MPPE required, but keys are not available. " + "Possible plugin problem?")); lcp_close(pcb, "MPPE required but not available"); return; } @@ -611,7 +611,7 @@ static void ccp_resetci(fsm *f) { if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { /* This might be noise */ if (go->mppe & MPPE_OPT_40) { - ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); + ppp_notice(("Disabling 40-bit MPPE; MS-CHAP LM not supported")); go->mppe &= ~MPPE_OPT_40; wo->mppe &= ~MPPE_OPT_40; } @@ -620,7 +620,7 @@ static void ccp_resetci(fsm *f) { /* Last check: can we actually negotiate something? */ if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { /* Could be misconfig, could be 40-bit disabled above. */ - ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); + ppp_error(("MPPE required, but both 40-bit and 128-bit disabled.")); lcp_close(pcb, "MPPE required but not available"); return; } @@ -949,7 +949,7 @@ static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { */ MPPE_CI_TO_OPTS(&p[2], try_.mppe); if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); + ppp_error(("Refusing MPPE stateful mode offered by peer")); try_.mppe = 0; } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { /* Peer must have set options we didn't request (suggest) */ @@ -957,7 +957,7 @@ static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { } if (!try_.mppe) { - ppp_error("MPPE required but peer negotiation failed"); + ppp_error(("MPPE required but peer negotiation failed")); lcp_close(pcb, "MPPE required but peer negotiation failed"); } } @@ -1035,7 +1035,7 @@ static int ccp_rejci(fsm *f, u_char *p, int len) { #if MPPE_SUPPORT if (go->mppe && len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { - ppp_error("MPPE required but peer refused"); + ppp_error(("MPPE required but peer refused")); lcp_close(pcb, "MPPE required but peer refused"); p += CILEN_MPPE; len -= CILEN_MPPE; @@ -1164,7 +1164,7 @@ static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { * the Internet -- which is where we expect MPPE. */ if (pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); + ppp_error(("Refusing MPPE stateful mode offered by peer")); newret = CONFREJ; break; } @@ -1213,9 +1213,9 @@ static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { * because MPPE frames **grow**. The kernel [must] * allocate MPPE_PAD extra bytes in xmit buffers. */ - mtu = netif_get_mtu(pcb); + mtu = ppp_netif_get_mtu(pcb); if (mtu) - netif_set_mtu(pcb, mtu - MPPE_PAD); + ppp_netif_set_mtu(pcb, mtu - MPPE_PAD); else newret = CONFREJ; } @@ -1375,7 +1375,7 @@ static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { } #if MPPE_SUPPORT if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { - ppp_error("MPPE required but peer negotiation failed"); + ppp_error(("MPPE required but peer negotiation failed")); lcp_close(pcb, "MPPE required but peer negotiation failed"); } #endif /* MPPE_SUPPORT */ @@ -1466,16 +1466,16 @@ static void ccp_up(fsm *f) { if (ccp_anycompress(go)) { if (ccp_anycompress(ho)) { if (go->method == ho->method) { - ppp_notice("%s compression enabled", method_name(go, ho)); + ppp_notice(("%s compression enabled", method_name(go, ho))); } else { ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); - ppp_notice("%s / %s compression enabled", - method1, method_name(ho, NULL)); + ppp_notice(("%s / %s compression enabled", + method1, method_name(ho, NULL))); } } else - ppp_notice("%s receive compression enabled", method_name(go, NULL)); + ppp_notice(("%s receive compression enabled", method_name(go, NULL))); } else if (ccp_anycompress(ho)) - ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); + ppp_notice(("%s transmit compression enabled", method_name(ho, NULL))); #if MPPE_SUPPORT if (go->mppe) { continue_networks(pcb); /* Bring up IP et al */ @@ -1501,7 +1501,7 @@ static void ccp_down(fsm *f) { go->mppe = 0; if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { /* If LCP is not already going down, make sure it does. */ - ppp_error("MPPE disabled"); + ppp_error(("MPPE disabled")); lcp_close(pcb, "MPPE disabled"); } } @@ -1671,14 +1671,14 @@ static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { /* * Disable compression by taking CCP down. */ - ppp_error("Lost compression sync: disabling compression"); + ppp_error(("Lost compression sync: disabling compression")); ccp_close(pcb, "Lost compression sync"); #if MPPE_SUPPORT /* * If we were doing MPPE, we must also take the link down. */ if (go->mppe) { - ppp_error("Too many MPPE errors, closing LCP"); + ppp_error(("Too many MPPE errors, closing LCP")); lcp_close(pcb, "Too many MPPE errors"); } #endif /* MPPE_SUPPORT */ diff --git a/src/netif/ppp/chap-new.c b/src/netif/ppp/chap-new.c index 485122d..da12430 100644 --- a/src/netif/ppp/chap-new.c +++ b/src/netif/ppp/chap-new.c @@ -166,15 +166,15 @@ void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { int i; if (pcb->chap_server.flags & AUTH_STARTED) { - ppp_error("CHAP: peer authentication already started!"); + ppp_error(("CHAP: peer authentication already started!")); return; } for (i = 0; (dp = chap_digests[i]) != NULL; ++i) if (dp->code == digest_code) break; if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); + ppp_fatal(("CHAP digest 0x%x requested but not available", + digest_code)); pcb->chap_server.digest = dp; pcb->chap_server.name = our_name; @@ -198,7 +198,7 @@ void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { return; if (pcb->chap_client.flags & AUTH_STARTED) { - ppp_error("CHAP: authentication with peer already started!"); + ppp_error(("CHAP: authentication with peer already started!")); return; } for (i = 0; (dp = chap_digests[i]) != NULL; ++i) @@ -206,8 +206,8 @@ void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { break; if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); + ppp_fatal(("CHAP digest 0x%x requested but not available", + digest_code)); pcb->chap_client.digest = dp; pcb->chap_client.name = our_name; @@ -236,7 +236,7 @@ static void chap_timeout(void *arg) { return; } - p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -337,7 +337,7 @@ static void chap_handle_response(ppp_pcb *pcb, int id, #endif /* UNUSED */ if (!ok) { pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP authentication", name); + ppp_warn(("Peer %q failed CHAP authentication", name)); } } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) return; @@ -345,7 +345,7 @@ static void chap_handle_response(ppp_pcb *pcb, int id, /* send the response */ mlen = strlen(message); len = CHAP_HDRLEN + mlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -381,7 +381,7 @@ static void chap_handle_response(ppp_pcb *pcb, int id, if (session_mgmt && session_check(name, NULL, devnam, NULL) == 0) { pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP Session verification", name); + ppp_warn(("Peer %q failed CHAP Session verification", name)); } #endif /* UNUSED */ @@ -418,7 +418,7 @@ static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourn /* Get the secret that the peer is supposed to know */ if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { - ppp_error("No CHAP secret found for authenticating %q", name); + ppp_error(("No CHAP secret found for authenticating %q", name)); return 0; } ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, @@ -441,7 +441,7 @@ static void chap_respond(ppp_pcb *pcb, int id, char rname[MAXNAMELEN+1]; char secret[MAXSECRETLEN+1]; - p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -468,7 +468,7 @@ static void chap_respond(ppp_pcb *pcb, int id, /* get secret for authenticating ourselves with the specified host */ if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { secret_len = 0; /* assume null secret if can't find one */ - ppp_warn("No CHAP secret found for authenticating us to %q", rname); + ppp_warn(("No CHAP secret found for authenticating us to %q", rname)); } outp = (u_char*)p->payload; @@ -519,15 +519,15 @@ static void chap_handle_status(ppp_pcb *pcb, int code, int id, } if (msg) { if (len > 0) - ppp_info("%s: %.*v", msg, len, pkt); + ppp_info(("%s: %.*v", msg, len, pkt)); else - ppp_info("%s", msg); + ppp_info(("%s", msg)); } if (code == CHAP_SUCCESS) auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); else { pcb->chap_client.flags |= AUTH_FAILED; - ppp_error("CHAP authentication failed"); + ppp_error(("CHAP authentication failed")); auth_withpeer_fail(pcb, PPP_CHAP); } } @@ -577,7 +577,7 @@ static void chap_protrej(ppp_pcb *pcb) { #endif /* PPP_SERVER */ if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { pcb->chap_client.flags &= ~AUTH_STARTED; - ppp_error("CHAP authentication failed due to protocol-reject"); + ppp_error(("CHAP authentication failed due to protocol-reject")); auth_withpeer_fail(pcb, PPP_CHAP); } } diff --git a/src/netif/ppp/chap_ms.c b/src/netif/ppp/chap_ms.c index 5a989c9..0639e7d 100644 --- a/src/netif/ppp/chap_ms.c +++ b/src/netif/ppp/chap_ms.c @@ -33,7 +33,7 @@ * * Implemented LANManager type password response to MS-CHAP challenges. * Now pppd provides both NT style and LANMan style blocks, and the - * prefered is set by option "ms-lanman". Default is to use NT. + * preferred is set by option "ms-lanman". Default is to use NT. * The hash text (StdText) was taken from Win95 RASAPI32.DLL. * * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 @@ -264,7 +264,7 @@ static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, #ifndef MSLANMAN if (!response[MS_CHAP_USENT]) { /* Should really propagate this into the error packet. */ - ppp_notice("Peer request for LANMAN auth not supported"); + ppp_notice(("Peer request for LANMAN auth not supported")); goto bad; } #endif @@ -404,7 +404,7 @@ static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsi if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || strncmp((char *)msg, "S=", 2) != 0) { /* Packet does not start with "S=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); + ppp_error(("MS-CHAPv2 Success packet is badly formed.")); return 0; } msg += 2; @@ -412,7 +412,7 @@ static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsi if (len < MS_AUTH_RESPONSE_LENGTH || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { /* Authenticator Response did not match expected. */ - ppp_error("MS-CHAPv2 mutual authentication failed."); + ppp_error(("MS-CHAPv2 mutual authentication failed.")); return 0; } /* Authenticator Response matches. */ @@ -422,7 +422,7 @@ static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsi msg += 3; /* Eat the delimiter */ } else if (len) { /* Packet has extra text which does not begin " M=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); + ppp_error(("MS-CHAPv2 Success packet is badly formed.")); return 0; } return 1; @@ -483,14 +483,14 @@ static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { break; default: - ppp_error("Unknown MS-CHAP authentication failure: %.*v", - len, inp); + ppp_error(("Unknown MS-CHAP authentication failure: %.*v", + len, inp)); return; } } print_msg: if (p != NULL) - ppp_error("MS-CHAP authentication failed: %v", p); + ppp_error(("MS-CHAP authentication failed: %v", p)); } static void ChallengeResponse(const u_char *challenge, diff --git a/src/netif/ppp/demand.c b/src/netif/ppp/demand.c index 26c6c30..709e5ea 100644 --- a/src/netif/ppp/demand.c +++ b/src/netif/ppp/demand.c @@ -86,8 +86,8 @@ demand_conf() const struct protent *protp; /* framemax = lcp_allowoptions[0].mru; - if (framemax < PPP_MRU) */ - framemax = PPP_MRU; + if (framemax < PPP_DEFMRU) */ + framemax = PPP_DEFMRU; framemax += PPP_HDRLEN + PPP_FCSLEN; frame = malloc(framemax); if (frame == NULL) @@ -98,9 +98,9 @@ demand_conf() flush_flag = 0; fcs = PPP_INITFCS; - netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); - if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) + ppp_netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_DEFMRU)); + if (ppp_send_config(pcb, PPP_DEFMRU, (u32_t) 0, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_DEFMRU, (u32_t) 0, 0, 0) < 0) fatal("Couldn't set up demand-dialled PPP interface: %m"); #ifdef PPP_FILTER diff --git a/src/netif/ppp/eap.c b/src/netif/ppp/eap.c index 8fb5636..ea684bf 100644 --- a/src/netif/ppp/eap.c +++ b/src/netif/ppp/eap.c @@ -13,7 +13,7 @@ * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Original version by James Carlson * @@ -211,7 +211,7 @@ static void eap_client_timeout(void *arg) { if (!eap_client_active(pcb)) return; - ppp_error("EAP: timeout waiting for Request from peer"); + ppp_error(("EAP: timeout waiting for Request from peer")); auth_withpeer_fail(pcb, PPP_EAP); pcb->eap.es_client.ea_state = eapBadAuth; } @@ -251,7 +251,7 @@ static void eap_send_failure(ppp_pcb *pcb) { struct pbuf *p; u_char *outp; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -282,7 +282,7 @@ static void eap_send_success(ppp_pcb *pcb) { struct pbuf *p; u_char *outp; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -471,8 +471,8 @@ static void eap_figure_next_state(ppp_pcb *pcb, int status) { toffs -= 86400; /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ if (!DesDecrypt(secbuf, clear)) { - ppp_dbglog("no DES here; cannot decode " - "pseudonym"); + ppp_dbglog(("no DES here; cannot decode " + "pseudonym")); return; } id = *(unsigned char *)clear; @@ -502,11 +502,11 @@ static void eap_figure_next_state(ppp_pcb *pcb, int status) { } pcb->eap.es_server.ea_peer[ pcb->eap.es_server.ea_peerlen] = '\0'; - ppp_dbglog("decoded pseudonym to \"%.*q\"", + ppp_dbglog(("decoded pseudonym to \"%.*q\"", pcb->eap.es_server.ea_peerlen, - pcb->eap.es_server.ea_peer); + pcb->eap.es_server.ea_peer)); } else { - ppp_dbglog("failed to decode real name"); + ppp_dbglog(("failed to decode real name")); /* Stay in eapIdentfy state; requery */ break; } @@ -676,14 +676,14 @@ static void eap_send_request(ppp_pcb *pcb) { if (pcb->settings.eap_max_transmits > 0 && pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { if (pcb->eap.es_server.ea_responses > 0) - ppp_error("EAP: too many Requests sent"); + ppp_error(("EAP: too many Requests sent")); else - ppp_error("EAP: no response to Requests"); + ppp_error(("EAP: no response to Requests")); eap_send_failure(pcb); return; } - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_UNKNOWN_SIZE), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -786,7 +786,7 @@ static void eap_send_request(ppp_pcb *pcb) { cp += j; /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ if (!DesEncrypt(clear, cipher)) { - ppp_dbglog("no DES here; not generating pseudonym"); + ppp_dbglog(("no DES here; not generating pseudonym")); break; } BZERO(&b64, sizeof (b64)); @@ -997,12 +997,12 @@ static void eap_lowerdown(ppp_pcb *pcb) { static void eap_protrej(ppp_pcb *pcb) { if (eap_client_active(pcb)) { - ppp_error("EAP authentication failed due to Protocol-Reject"); + ppp_error(("EAP authentication failed due to Protocol-Reject")); auth_withpeer_fail(pcb, PPP_EAP); } #if PPP_SERVER if (eap_server_active(pcb)) { - ppp_error("EAP authentication of peer failed on Protocol-Reject"); + ppp_error(("EAP authentication of peer failed on Protocol-Reject")); auth_peer_fail(pcb, PPP_EAP); } #endif /* PPP_SERVER */ @@ -1018,7 +1018,7 @@ static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_c int msglen; msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -1052,7 +1052,7 @@ static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + namelen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -1097,7 +1097,7 @@ int lenstr; int msglen; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -1139,7 +1139,7 @@ u_char *str; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + SHA_DIGESTSIZE; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -1170,7 +1170,7 @@ static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { int msglen; msglen = EAP_HEADERLEN + 2 * sizeof (u_char); - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -1213,7 +1213,7 @@ name_of_pn_file() return (NULL); (void) slprintf(path, pl, "%s/%s", user, file); if (!pnlogged) { - ppp_dbglog("pseudonym file: %s", path); + ppp_dbglog(("pseudonym file: %s", path)); pnlogged = 1; } return (path); @@ -1284,22 +1284,22 @@ int len, id; /* Now check that the result is sane */ if (olen <= 0 || *inp + 1 > olen) { - ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); + ppp_dbglog(("EAP: decoded pseudonym is unusable <%.*B>", olen, inp)); return; } /* Save it away */ fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); if (fd < 0) { - ppp_dbglog("EAP: error saving pseudonym: %m"); + ppp_dbglog(("EAP: error saving pseudonym: %m")); return; } len = write(fd, inp + 1, *inp); if (close(fd) != -1 && len == *inp) { - ppp_dbglog("EAP: saved pseudonym"); + ppp_dbglog(("EAP: saved pseudonym")); pcb->eap.es_usedpseudo = 0; } else { - ppp_dbglog("EAP: failed to save pseudonym"); + ppp_dbglog(("EAP: failed to save pseudonym")); remove_pn_file(); } } @@ -1325,6 +1325,12 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { int fd; #endif /* USE_SRP */ + /* + * Ignore requests if we're not open + */ + if (pcb->eap.es_client.ea_state <= eapClosed) + return; + /* * Note: we update es_client.ea_id *only if* a Response * message is being generated. Otherwise, we leave it the @@ -1334,7 +1340,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { pcb->eap.es_client.ea_requests++; if (pcb->settings.eap_allow_req != 0 && pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { - ppp_info("EAP: received too many Request messages"); + ppp_info(("EAP: received too many Request messages")); if (pcb->settings.eap_req_time > 0) { UNTIMEOUT(eap_client_timeout, pcb); } @@ -1343,7 +1349,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { } if (len <= 0) { - ppp_error("EAP: empty Request message discarded"); + ppp_error(("EAP: empty Request message discarded")); return; } @@ -1353,7 +1359,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { switch (typenum) { case EAPT_IDENTITY: if (len > 0) - ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); + ppp_info(("EAP: Identity prompt \"%.*q\"", len, inp)); #ifdef USE_SRP if (pcb->eap.es_usepseudo && (pcb->eap.es_usedpseudo == 0 || @@ -1387,7 +1393,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPT_NOTIFICATION: if (len > 0) - ppp_info("EAP: Notification \"%.*q\"", len, inp); + ppp_info(("EAP: Notification \"%.*q\"", len, inp)); eap_send_response(pcb, id, typenum, NULL, 0); break; @@ -1396,29 +1402,29 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { * Avoid the temptation to send Response Nak in reply * to Request Nak here. It can only lead to trouble. */ - ppp_warn("EAP: unexpected Nak in Request; ignored"); + ppp_warn(("EAP: unexpected Nak in Request; ignored")); /* Return because we're waiting for something real. */ return; case EAPT_MD5CHAP: if (len < 1) { - ppp_error("EAP: received MD5-Challenge with no data"); + ppp_error(("EAP: received MD5-Challenge with no data")); /* Bogus request; wait for something real. */ return; } GETCHAR(vallen, inp); len--; if (vallen < 8 || vallen > len) { - ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", - vallen, len); + ppp_error(("EAP: MD5-Challenge with bad length %d (8..%d)", + vallen, len)); /* Try something better. */ eap_send_nak(pcb, id, EAPT_SRP); break; } /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); + if (len - vallen >= (int)sizeof (rhostname)) { + ppp_dbglog(("EAP: trimming really long peer name down")); MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); rhostname[sizeof (rhostname) - 1] = '\0'; } else { @@ -1439,7 +1445,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { */ if (!get_secret(pcb, pcb->eap.es_client.ea_name, rhostname, secret, &secret_len, 0)) { - ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); + ppp_dbglog(("EAP: no MD5 secret for auth to %q", rhostname)); eap_send_nak(pcb, id, EAPT_SRP); break; } @@ -1459,7 +1465,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { #ifdef USE_SRP case EAPT_SRP: if (len < 1) { - ppp_error("EAP: received empty SRP Request"); + ppp_error(("EAP: received empty SRP Request")); /* Bogus request; wait for something real. */ return; } @@ -1492,8 +1498,8 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { GETCHAR(vallen, inp); len--; if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (name)"); + ppp_error(("EAP: badly-formed SRP Challenge" + " (name)")); /* Ignore badly-formed messages */ return; } @@ -1523,8 +1529,8 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { GETCHAR(vallen, inp); len--; if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (s)"); + ppp_error(("EAP: badly-formed SRP Challenge" + " (s)")); /* Ignore badly-formed messages */ return; } @@ -1536,8 +1542,8 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { GETCHAR(vallen, inp); len--; if (vallen > len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (g)"); + ppp_error(("EAP: badly-formed SRP Challenge" + " (g)")); /* Ignore badly-formed messages */ return; } @@ -1584,7 +1590,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_SKEY: tc = (struct t_client *)pcb->eap.es_client.ea_session; if (tc == NULL) { - ppp_warn("EAP: peer sent Subtype 2 without 1"); + ppp_warn(("EAP: peer sent Subtype 2 without 1")); eap_send_nak(pcb, id, EAPT_MD5CHAP); break; } @@ -1594,9 +1600,9 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { * if it does (but otherwise ignore). */ if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " + ppp_warn(("EAP: ID changed from %d to %d " "in SRP Subtype 2 rexmit", - pcb->eap.es_client.ea_id, id); + pcb->eap.es_client.ea_id, id)); } } else { if (get_srp_secret(pcb->eap.es_unit, @@ -1618,7 +1624,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { t_clientgetkey(tc, &Bval); if (pcb->eap.es_client.ea_skey == NULL) { /* Server is rogue; stop now */ - ppp_error("EAP: SRP server is rogue"); + ppp_error(("EAP: SRP server is rogue")); goto client_failure; } } @@ -1629,7 +1635,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_SVALIDATOR: tc = (struct t_client *)pcb->eap.es_client.ea_session; if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { - ppp_warn("EAP: peer sent Subtype 3 without 1/2"); + ppp_warn(("EAP: peer sent Subtype 3 without 1/2")); eap_send_nak(pcb, id, EAPT_MD5CHAP); break; } @@ -1640,16 +1646,16 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { */ if (pcb->eap.es_client.ea_state == eapOpen) { if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " + ppp_warn(("EAP: ID changed from %d to %d " "in SRP Subtype 3 rexmit", - pcb->eap.es_client.ea_id, id); + pcb->eap.es_client.ea_id, id)); } } else { len -= sizeof (u32_t) + SHA_DIGESTSIZE; if (len < 0 || t_clientverify(tc, inp + sizeof (u32_t)) != 0) { - ppp_error("EAP: SRP server verification " - "failed"); + ppp_error(("EAP: SRP server verification " + "failed")); goto client_failure; } GETLONG(pcb->eap.es_client.ea_keyflags, inp); @@ -1669,7 +1675,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_LWRECHALLENGE: if (len < 4) { - ppp_warn("EAP: malformed Lightweight rechallenge"); + ppp_warn(("EAP: malformed Lightweight rechallenge")); return; } SHA1Init(&ctxt); @@ -1686,7 +1692,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { break; default: - ppp_error("EAP: unknown SRP Subtype %d", vallen); + ppp_error(("EAP: unknown SRP Subtype %d", vallen)); eap_send_nak(pcb, id, EAPT_MD5CHAP); break; } @@ -1694,7 +1700,7 @@ static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { #endif /* USE_SRP */ default: - ppp_info("EAP: unknown authentication type %d; Naking", typenum); + ppp_info(("EAP: unknown authentication type %d; Naking", typenum)); eap_send_nak(pcb, id, EAPT_SRP); break; } @@ -1737,16 +1743,22 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { u_char dig[SHA_DIGESTSIZE]; #endif /* USE_SRP */ + /* + * Ignore responses if we're not open + */ + if (pcb->eap.es_server.ea_state <= eapClosed) + return; + if (pcb->eap.es_server.ea_id != id) { - ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, - pcb->eap.es_server.ea_id); + ppp_dbglog(("EAP: discarding Response %d; expected ID %d", id, + pcb->eap.es_server.ea_id)); return; } pcb->eap.es_server.ea_responses++; if (len <= 0) { - ppp_error("EAP: empty Response message discarded"); + ppp_error(("EAP: empty Response message discarded")); return; } @@ -1756,11 +1768,11 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { switch (typenum) { case EAPT_IDENTITY: if (pcb->eap.es_server.ea_state != eapIdentify) { - ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, - inp); + ppp_dbglog(("EAP discarding unwanted Identify \"%.q\"", len, + inp)); break; } - ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); + ppp_info(("EAP: unauthenticated peer name \"%.*q\"", len, inp)); if (len > MAXNAMELEN) { len = MAXNAMELEN; } @@ -1771,12 +1783,12 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { break; case EAPT_NOTIFICATION: - ppp_dbglog("EAP unexpected Notification; response discarded"); + ppp_dbglog(("EAP unexpected Notification; response discarded")); break; case EAPT_NAK: if (len < 1) { - ppp_info("EAP: Nak Response with no suggested protocol"); + ppp_info(("EAP: Nak Response with no suggested protocol")); eap_figure_next_state(pcb, 1); break; } @@ -1806,7 +1818,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { break; default: - ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); + ppp_dbglog(("EAP: peer requesting unknown Type %d", vallen)); switch (pcb->eap.es_server.ea_state) { case eapSRP1: case eapSRP2: @@ -1827,26 +1839,26 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPT_MD5CHAP: if (pcb->eap.es_server.ea_state != eapMD5Chall) { - ppp_error("EAP: unexpected MD5-Response"); + ppp_error(("EAP: unexpected MD5-Response")); eap_figure_next_state(pcb, 1); break; } if (len < 1) { - ppp_error("EAP: received MD5-Response with no data"); + ppp_error(("EAP: received MD5-Response with no data")); eap_figure_next_state(pcb, 1); break; } GETCHAR(vallen, inp); len--; if (vallen != 16 || vallen > len) { - ppp_error("EAP: MD5-Response with bad length %d", vallen); + ppp_error(("EAP: MD5-Response with bad length %d", vallen)); eap_figure_next_state(pcb, 1); break; } /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); + if (len - vallen >= (int)sizeof (rhostname)) { + ppp_dbglog(("EAP: trimming really long peer name down")); MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); rhostname[sizeof (rhostname) - 1] = '\0'; } else { @@ -1867,7 +1879,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { */ if (!get_secret(pcb, rhostname, pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { - ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); + ppp_dbglog(("EAP: no MD5 secret for auth of %q", rhostname)); eap_send_failure(pcb); break; } @@ -1893,7 +1905,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { #ifdef USE_SRP case EAPT_SRP: if (len < 1) { - ppp_error("EAP: empty SRP Response"); + ppp_error(("EAP: empty SRP Response")); eap_figure_next_state(pcb, 1); break; } @@ -1902,7 +1914,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { switch (typenum) { case EAPSRP_CKEY: if (pcb->eap.es_server.ea_state != eapSRP1) { - ppp_error("EAP: unexpected SRP Subtype 1 Response"); + ppp_error(("EAP: unexpected SRP Subtype 1 Response")); eap_figure_next_state(pcb, 1); break; } @@ -1913,7 +1925,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); if (pcb->eap.es_server.ea_skey == NULL) { /* Client's A value is bogus; terminate now */ - ppp_error("EAP: bogus A value from client"); + ppp_error(("EAP: bogus A value from client")); eap_send_failure(pcb); } else { eap_figure_next_state(pcb, 0); @@ -1922,13 +1934,13 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_CVALIDATOR: if (pcb->eap.es_server.ea_state != eapSRP2) { - ppp_error("EAP: unexpected SRP Subtype 2 Response"); + ppp_error(("EAP: unexpected SRP Subtype 2 Response")); eap_figure_next_state(pcb, 1); break; } if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { - ppp_error("EAP: M1 length %d < %d", len, - sizeof (u32_t) + SHA_DIGESTSIZE); + ppp_error(("EAP: M1 length %d < %d", len, + sizeof (u32_t) + SHA_DIGESTSIZE)); eap_figure_next_state(pcb, 1); break; } @@ -1936,7 +1948,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { ts = (struct t_server *)pcb->eap.es_server.ea_session; assert(ts != NULL); if (t_serververify(ts, inp)) { - ppp_info("EAP: unable to validate client identity"); + ppp_info(("EAP: unable to validate client identity")); eap_send_failure(pcb); break; } @@ -1945,7 +1957,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_ACK: if (pcb->eap.es_server.ea_state != eapSRP3) { - ppp_error("EAP: unexpected SRP Subtype 3 Response"); + ppp_error(("EAP: unexpected SRP Subtype 3 Response")); eap_send_failure(esp); break; } @@ -1962,12 +1974,12 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { case EAPSRP_LWRECHALLENGE: if (pcb->eap.es_server.ea_state != eapSRP4) { - ppp_info("EAP: unexpected SRP Subtype 4 Response"); + ppp_info(("EAP: unexpected SRP Subtype 4 Response")); return; } if (len != SHA_DIGESTSIZE) { - ppp_error("EAP: bad Lightweight rechallenge " - "response"); + ppp_error(("EAP: bad Lightweight rechallenge " + "response")); return; } SHA1Init(&ctxt); @@ -1980,7 +1992,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { pcb->eap.es_server.ea_peerlen); SHA1Final(dig, &ctxt); if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { - ppp_error("EAP: failed Lightweight rechallenge"); + ppp_error(("EAP: failed Lightweight rechallenge")); eap_send_failure(pcb); break; } @@ -1995,7 +2007,7 @@ static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { default: /* This can't happen. */ - ppp_error("EAP: unknown Response type %d; ignored", typenum); + ppp_error(("EAP: unknown Response type %d; ignored", typenum)); return; } @@ -2018,9 +2030,9 @@ static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { LWIP_UNUSED_ARG(id); if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected success message in state %s (%d)", + ppp_dbglog(("EAP unexpected success message in state %s (%d)", eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); + pcb->eap.es_client.ea_state)); return; } @@ -2043,10 +2055,16 @@ static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { LWIP_UNUSED_ARG(id); + /* + * Ignore failure messages if we're not open + */ + if (pcb->eap.es_client.ea_state <= eapClosed) + return; + if (!eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected failure message in state %s (%d)", + ppp_dbglog(("EAP unexpected failure message in state %s (%d)", eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); + pcb->eap.es_client.ea_state)); } if (pcb->settings.eap_req_time > 0) { @@ -2060,7 +2078,7 @@ static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { pcb->eap.es_client.ea_state = eapBadAuth; - ppp_error("EAP: peer reports authentication failure"); + ppp_error(("EAP: peer reports authentication failure")); auth_withpeer_fail(pcb, PPP_EAP); } @@ -2076,15 +2094,15 @@ static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { * drop it. */ if (inlen < EAP_HEADERLEN) { - ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); + ppp_error(("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN)); return; } GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); if (len < EAP_HEADERLEN || len > inlen) { - ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, - EAP_HEADERLEN, inlen); + ppp_error(("EAP: packet has illegal length field %d (%d..%d)", len, + EAP_HEADERLEN, inlen)); return; } len -= EAP_HEADERLEN; @@ -2111,7 +2129,7 @@ static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { default: /* XXX Need code reject */ /* Note: it's not legal to send EAP Nak here. */ - ppp_warn("EAP: unknown code %d received", code); + ppp_warn(("EAP: unknown code %d received", code)); break; } } diff --git a/src/netif/ppp/eap.h b/src/netif/ppp/eap.h index 3ee9aaf..32434ed 100644 --- a/src/netif/ppp/eap.h +++ b/src/netif/ppp/eap.h @@ -13,7 +13,7 @@ * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Original version by James Carlson * diff --git a/src/netif/ppp/fsm.c b/src/netif/ppp/fsm.c index b1f08af..90a227c 100644 --- a/src/netif/ppp/fsm.c +++ b/src/netif/ppp/fsm.c @@ -290,7 +290,7 @@ static void fsm_timeout(void *arg) { case PPP_FSM_ACKRCVD: case PPP_FSM_ACKSENT: if (f->retransmits <= 0) { - ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); + ppp_warn(("%s: timeout sending Config-Requests", PROTO_NAME(f))); f->state = PPP_FSM_STOPPED; if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) (*f->callbacks->finished)(f); @@ -464,7 +464,7 @@ static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ){ /* Ack is bad - ignore it */ - ppp_error("Received bad configure-ack: %P", inp, len); + ppp_error(("Received bad configure-ack: %P", inp, len)); return; } f->seen_ack = 1; @@ -524,14 +524,14 @@ static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { treat_as_reject = (f->rnakloops >= f->maxnakloops); if (f->callbacks->nakci == NULL || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { - ppp_error("Received bad configure-nak: %P", inp, len); + ppp_error(("Received bad configure-nak: %P", inp, len)); return; } } else { f->rnakloops = 0; if (f->callbacks->rejci == NULL || !(ret = f->callbacks->rejci(f, inp, len))) { - ppp_error("Received bad configure-rej: %P", inp, len); + ppp_error(("Received bad configure-rej: %P", inp, len)); return; } } @@ -588,9 +588,9 @@ static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { case PPP_FSM_OPENED: if (len > 0) { - ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); + ppp_info(("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p)); } else - ppp_info("%s terminated by peer", PROTO_NAME(f)); + ppp_info(("%s terminated by peer", PROTO_NAME(f))); f->retransmits = 0; f->state = PPP_FSM_STOPPING; if (f->callbacks->down) @@ -651,7 +651,7 @@ static void fsm_rcoderej(fsm *f, u_char *inp, int len) { } GETCHAR(code, inp); GETCHAR(id, inp); - ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); + ppp_warn(("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id)); if( f->state == PPP_FSM_ACKRCVD ) f->state = PPP_FSM_REQSENT; @@ -735,7 +735,7 @@ static void fsm_sconfreq(fsm *f, int retransmit) { } else cilen = 0; - p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -778,7 +778,7 @@ void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) datalen = pcb->peer_mru - HEADERLEN; outlen = datalen + HEADERLEN; - p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -787,8 +787,9 @@ void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) } outp = (u_char*)p->payload; - if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ - MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + if (datalen && data != NULL) { /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ + MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + } MAKEHEADER(outp, f->protocol); PUTCHAR(code, outp); PUTCHAR(id, outp); diff --git a/src/netif/ppp/ipcp.c b/src/netif/ppp/ipcp.c index b7c766e..b033cde 100644 --- a/src/netif/ppp/ipcp.c +++ b/src/netif/ppp/ipcp.c @@ -1067,7 +1067,7 @@ static int ipcp_ackci(fsm *f, u_char *p, int len) { * ipcp_nakci - Peer has sent a NAK for some of our CIs. * This should not modify any state if the Nak is bad * or if IPCP is in the OPENED state. - * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + * Callback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. * * Returns: * 0 - Nak was bad. @@ -1537,7 +1537,7 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { next = inp; while (l) { orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ + cip = p = next; /* Remember beginning of CI */ if (l < 2 || /* Not enough data for CI header or */ p[1] < 2 || /* CI length too small or */ p[1] > l) { /* CI length too big? */ @@ -1589,7 +1589,7 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { * If he doesn't know our address, or if we both have our address * but disagree about it, then NAK it with our idea. */ - GETLONG(tl, p); /* Parse desination address (ours) */ + GETLONG(tl, p); /* Parse destination address (ours) */ ciaddr2 = lwip_htonl(tl); if (ciaddr2 != wo->ouraddr) { if (ciaddr2 == 0 || !wo->accept_local) { @@ -1739,7 +1739,7 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { } endswitch: if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ + rc != CONFACK) /* but prior CI wasn't? */ continue; /* Don't send this one */ if (orc == CONFNAK) { /* Nak this CI? */ @@ -1869,9 +1869,9 @@ ip_demand_conf(u) proxy_arp_set[u] = 1; #endif /* UNUSED - PROXY ARP */ - ppp_notice("local IP address %I", wo->ouraddr); + ppp_notice(("local IP address %I", wo->ouraddr)); if (wo->hisaddr) - ppp_notice("remote IP address %I", wo->hisaddr); + ppp_notice(("remote IP address %I", wo->hisaddr)); return 1; } @@ -1899,19 +1899,19 @@ static void ipcp_up(fsm *f) { if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) && wo->ouraddr != 0) { - ppp_error("Peer refused to agree to our IP address"); + ppp_error(("Peer refused to agree to our IP address")); ipcp_close(f->pcb, "Refused our IP address"); return; } if (go->ouraddr == 0) { - ppp_error("Could not determine local IP address"); + ppp_error(("Could not determine local IP address")); ipcp_close(f->pcb, "Could not determine local IP address"); return; } if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { ho->hisaddr = lwip_htonl(0x0a404040); - ppp_warn("Could not determine remote IP address: defaulting to %I", - ho->hisaddr); + ppp_warn(("Could not determine remote IP address: defaulting to %I", + ho->hisaddr)); } #if 0 /* UNUSED */ script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); @@ -1955,7 +1955,7 @@ static void ipcp_up(fsm *f) { || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr) #endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ ) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ppp_error(("Peer is not authorized to use remote address %I", ho->hisaddr)); ipcp_close(pcb, "Unauthorized remote IP address"); return; } @@ -1963,7 +1963,7 @@ static void ipcp_up(fsm *f) { #if 0 /* Unused */ /* Upstream checking code */ if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ppp_error(("Peer is not authorized to use remote address %I", ho->hisaddr)); ipcp_close(f->unit, "Unauthorized remote IP address"); return; } @@ -1985,13 +1985,13 @@ static void ipcp_up(fsm *f) { ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, wo->replace_default_route); if (go->ouraddr != wo->ouraddr) { - ppp_warn("Local IP address changed to %I", go->ouraddr); + ppp_warn(("Local IP address changed to %I", go->ouraddr)); script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); wo->ouraddr = go->ouraddr; } else script_unsetenv("OLDIPLOCAL"); if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { - ppp_warn("Remote IP address changed to %I", ho->hisaddr); + ppp_warn(("Remote IP address changed to %I", ho->hisaddr)); script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); wo->hisaddr = ho->hisaddr; } else @@ -2001,7 +2001,7 @@ static void ipcp_up(fsm *f) { mask = get_mask(go->ouraddr); if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { #if PPP_DEBUG - ppp_warn("Interface configuration failed"); + ppp_warn(("Interface configuration failed")); #endif /* PPP_DEBUG */ ipcp_close(f->unit, "Interface configuration failed"); return; @@ -2035,7 +2035,7 @@ static void ipcp_up(fsm *f) { #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { #if PPP_DEBUG - ppp_warn("Interface configuration failed"); + ppp_warn(("Interface configuration failed")); #endif /* PPP_DEBUG */ ipcp_close(f->pcb, "Interface configuration failed"); return; @@ -2045,7 +2045,7 @@ static void ipcp_up(fsm *f) { /* bring the interface up for IP */ if (!sifup(pcb)) { #if PPP_DEBUG - ppp_warn("Interface failed to come up"); + ppp_warn(("Interface failed to come up")); #endif /* PPP_DEBUG */ ipcp_close(f->pcb, "Interface configuration failed"); return; @@ -2054,7 +2054,7 @@ static void ipcp_up(fsm *f) { #if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { #if PPP_DEBUG - ppp_warn("Interface configuration failed"); + ppp_warn(("Interface configuration failed")); #endif /* PPP_DEBUG */ ipcp_close(f->unit, "Interface configuration failed"); return; @@ -2081,14 +2081,14 @@ static void ipcp_up(fsm *f) { wo->ouraddr = go->ouraddr; - ppp_notice("local IP address %I", go->ouraddr); + ppp_notice(("local IP address %I", go->ouraddr)); if (ho->hisaddr != 0) - ppp_notice("remote IP address %I", ho->hisaddr); + ppp_notice(("remote IP address %I", ho->hisaddr)); #if LWIP_DNS if (go->dnsaddr[0]) - ppp_notice("primary DNS address %I", go->dnsaddr[0]); + ppp_notice(("primary DNS address %I", go->dnsaddr[0])); if (go->dnsaddr[1]) - ppp_notice("secondary DNS address %I", go->dnsaddr[1]); + ppp_notice(("secondary DNS address %I", go->dnsaddr[1])); #endif /* LWIP_DNS */ } diff --git a/src/netif/ppp/ipv6cp.c b/src/netif/ppp/ipv6cp.c index 11c18df..2035ef9 100644 --- a/src/netif/ppp/ipv6cp.c +++ b/src/netif/ppp/ipv6cp.c @@ -67,7 +67,7 @@ L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + sept laboratoires don't le laboratoire Logiciels, Systèmes, Réseaux (LSR). This work has been done in the context of GIE DYADE (joint R & D venture between BULL S.A. and INRIA). @@ -913,7 +913,7 @@ static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { next = inp; while (l) { orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ + cip = p = next; /* Remember beginning of CI */ if (l < 2 || /* Not enough data for CI header or */ p[1] < 2 || /* CI length too small or */ p[1] > l) { /* CI length too big? */ @@ -1006,7 +1006,7 @@ static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ + rc != CONFACK) /* but prior CI wasn't? */ continue; /* Don't send this one */ if (orc == CONFNAK) { /* Nak this CI? */ @@ -1134,9 +1134,9 @@ static int ipv6_demand_conf(int u) { if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) return 0; - ppp_notice("ipv6_demand_conf"); - ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); + ppp_notice(("ipv6_demand_conf")); + ppp_notice(("local LL address %s", llv6_ntoa(wo->ourid))); + ppp_notice(("remote LL address %s", llv6_ntoa(wo->hisid))); return 1; } @@ -1166,17 +1166,17 @@ static void ipv6cp_up(fsm *f) { if(!no_ifaceid_neg) { #endif /* UNUSED */ if (eui64_iszero(ho->hisid)) { - ppp_error("Could not determine remote LL address"); + ppp_error(("Could not determine remote LL address")); ipv6cp_close(f->pcb, "Could not determine remote LL address"); return; } if (eui64_iszero(go->ourid)) { - ppp_error("Could not determine local LL address"); + ppp_error(("Could not determine local LL address")); ipv6cp_close(f->pcb, "Could not determine local LL address"); return; } if (eui64_equals(go->ourid, ho->hisid)) { - ppp_error("local and remote LL addresses are equal"); + ppp_error(("local and remote LL addresses are equal")); ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); return; } @@ -1244,8 +1244,8 @@ static void ipv6cp_up(fsm *f) { sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); #endif /* DEMAND_SUPPORT */ - ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); + ppp_notice(("local LL address %s", llv6_ntoa(go->ourid))); + ppp_notice(("remote LL address %s", llv6_ntoa(ho->hisid))); } np_up(f->pcb, PPP_IPV6); diff --git a/src/netif/ppp/lcp.c b/src/netif/ppp/lcp.c index 90ed183..3bc0092 100644 --- a/src/netif/ppp/lcp.c +++ b/src/netif/ppp/lcp.c @@ -373,7 +373,7 @@ static void lcp_init(ppp_pcb *pcb) { BZERO(wo, sizeof(*wo)); wo->neg_mru = 1; - wo->mru = PPP_DEFMRU; + wo->mru = PPP_MRU; wo->neg_asyncmap = 1; wo->neg_magicnumber = 1; wo->neg_pcompression = 1; @@ -462,11 +462,11 @@ void lcp_lowerup(ppp_pcb *pcb) { * but accept A/C and protocol compressed packets * if we are going to ask for A/C and protocol compression. */ - if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), + if (ppp_send_config(pcb, PPP_DEFMRU, 0xffffffff, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_DEFMRU, (pcb->settings.lax_recv? 0: 0xffffffff), wo->neg_pcompression, wo->neg_accompression) < 0) return; - pcb->peer_mru = PPP_MRU; + pcb->peer_mru = PPP_DEFMRU; if (pcb->settings.listen_time != 0) { f->flags |= DELAYED_UP; @@ -594,22 +594,22 @@ static void lcp_rprotrej(fsm *f, u_char *inp, int len) { if (protp->protocol == prot) { #if PPP_PROTOCOLNAME if (pname != NULL) - ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, - prot); + ppp_dbglog(("Protocol-Reject for '%s' (0x%x) received", pname, + prot)); else #endif /* PPP_PROTOCOLNAME */ - ppp_dbglog("Protocol-Reject for 0x%x received", prot); + ppp_dbglog(("Protocol-Reject for 0x%x received", prot)); (*protp->protrej)(f->pcb); return; } #if PPP_PROTOCOLNAME if (pname != NULL) - ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, - prot); + ppp_warn(("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, + prot)); else #endif /* #if PPP_PROTOCOLNAME */ - ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); + ppp_warn(("Protocol-Reject for unsupported protocol 0x%x", prot)); } @@ -621,7 +621,7 @@ static void lcp_protrej(ppp_pcb *pcb) { /* * Can't reject LCP! */ - ppp_error("Received Protocol-Reject for LCP!"); + ppp_error(("Received Protocol-Reject for LCP!")); fsm_protreject(&pcb->lcp_fsm); } @@ -757,7 +757,7 @@ static void lcp_resetci(fsm *f) { #endif /* HAVE_MULTILINK */ if (pcb->settings.noendpoint) ao->neg_endpoint = 0; - pcb->peer_mru = PPP_MRU; + pcb->peer_mru = PPP_DEFMRU; #if 0 /* UNUSED */ auth_reset(pcb); #endif /* UNUSED */ @@ -931,7 +931,7 @@ static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { if (ucp - start_ucp != *lenp) { /* this should never happen, because peer_mtu should be 1500 */ - ppp_error("Bug in lcp_addci: wrong length"); + ppp_error(("Bug in lcp_addci: wrong length")); } } @@ -1363,7 +1363,7 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { * well, that's just strange. Nobody should do that. */ if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) - ppp_dbglog("Unexpected Conf-Nak for EAP"); + ppp_dbglog(("Unexpected Conf-Nak for EAP")); /* * We don't recognize what they're suggesting. @@ -1498,7 +1498,11 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { goto bad; break; case CI_AUTHTYPE: - if (0 + /* This is potentially dead code (#if !PPP_AUTH_SUPPORT) + * Thus the double parentheses to mark the code explicitly + * disabled when building with clang + */ + if ((0 #if CHAP_SUPPORT || go->neg_chap || no.neg_chap #endif /* CHAP_SUPPORT */ @@ -1508,7 +1512,7 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { #if EAP_SUPPORT || go->neg_eap || no.neg_eap #endif /* EAP_SUPPORT */ - ) + )) goto bad; break; case CI_MAGICNUMBER: @@ -1560,7 +1564,7 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { if (f->state != PPP_FSM_OPENED) { if (looped_back) { if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { - ppp_notice("Serial line is looped back."); + ppp_notice(("Serial line is looped back.")); pcb->err_code = PPPERR_LOOPBACK; lcp_close(f->pcb, "Loopback detected"); } @@ -1843,7 +1847,7 @@ static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { * Process all his options. */ next = inp; - nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_UNKNOWN_SIZE), PBUF_RAM); if(NULL == nakp) return 0; if(nakp->tot_len != nakp->len) { @@ -1855,7 +1859,7 @@ static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { rejp = inp; while (l) { orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ + cip = p = next; /* Remember beginning of CI */ if (l < 2 || /* Not enough data for CI header or */ p[1] < 2 || /* CI length too small or */ p[1] > l) { /* CI length too big? */ @@ -1935,7 +1939,7 @@ static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { /* * Reject the option if we're not willing to authenticate. */ - ppp_dbglog("No auth is possible"); + ppp_dbglog(("No auth is possible")); orc = CONFREJ; break; } @@ -2232,7 +2236,7 @@ static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { endswitch: if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ + rc != CONFACK) /* but prior CI wasn't? */ continue; /* Don't send this one */ if (orc == CONFNAK) { /* Nak this CI? */ @@ -2309,12 +2313,12 @@ static void lcp_up(fsm *f) { * the interface MTU is set to the lowest of that, the * MTU we want to use, and our link MRU. */ - mtu = ho->neg_mru? ho->mru: PPP_MRU; - mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; + mtu = ho->neg_mru? ho->mru: PPP_DEFMRU; + mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_DEFMRU; #ifdef HAVE_MULTILINK if (!(multilink && go->neg_mrru && ho->neg_mrru)) #endif /* HAVE_MULTILINK */ - netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); + ppp_netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); ppp_send_config(pcb, mtu, (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), ho->neg_pcompression, ho->neg_accompression); @@ -2344,11 +2348,11 @@ static void lcp_down(fsm *f) { link_down(pcb); - ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(pcb, PPP_MRU, + ppp_send_config(pcb, PPP_DEFMRU, 0xffffffff, 0, 0); + ppp_recv_config(pcb, PPP_DEFMRU, (go->neg_asyncmap? go->asyncmap: 0xffffffff), go->neg_pcompression, go->neg_accompression); - pcb->peer_mru = PPP_MRU; + pcb->peer_mru = PPP_DEFMRU; } @@ -2639,8 +2643,8 @@ static int lcp_printpkt(const u_char *p, int plen, static void LcpLinkFailure(fsm *f) { ppp_pcb *pcb = f->pcb; if (f->state == PPP_FSM_OPENED) { - ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); - ppp_notice("Serial link appears to be disconnected."); + ppp_info(("No response to %d echo-requests", pcb->lcp_echos_pending)); + ppp_notice(("Serial link appears to be disconnected.")); pcb->err_code = PPPERR_PEERDEAD; lcp_close(pcb, "Peer not responding"); } @@ -2661,7 +2665,7 @@ static void LcpEchoCheck(fsm *f) { * Start the timer for the next interval. */ if (pcb->lcp_echo_timer_running) - ppp_warn("assertion lcp_echo_timer_running==0 failed"); + ppp_warn(("assertion lcp_echo_timer_running==0 failed")); TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); pcb->lcp_echo_timer_running = 1; } @@ -2691,13 +2695,13 @@ static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { /* Check the magic number - don't count replies from ourselves. */ if (len < 4) { - ppp_dbglog("lcp: received short Echo-Reply, length %d", len); + ppp_dbglog(("lcp: received short Echo-Reply, length %d", len)); return; } GETLONG(magic_val, inp); if (go->neg_magicnumber && magic_val == go->magicnumber) { - ppp_warn("appear to have received our own echo-reply!"); + ppp_warn(("appear to have received our own echo-reply!")); return; } diff --git a/src/netif/ppp/magic.c b/src/netif/ppp/magic.c index d0d87c5..ce21326 100644 --- a/src/netif/ppp/magic.c +++ b/src/netif/ppp/magic.c @@ -114,12 +114,12 @@ static void magic_churnrand(char *rand_data, u32_t rand_len) { u32_t rand; #endif /* LWIP_RAND */ } sys_data; + /* Load sys_data fields here. */ magic_randomseed += sys_jiffies(); sys_data.jiffies = magic_randomseed; #ifdef LWIP_RAND sys_data.rand = LWIP_RAND(); #endif /* LWIP_RAND */ - /* Load sys_data fields here. */ lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); } lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); @@ -142,7 +142,7 @@ void magic_randomize(void) { } /* - * magic_random_bytes - Fill a buffer with random bytes. + * Fill a buffer with random bytes. * * Use the random pool to generate random data. This degrades to pseudo * random when used faster than randomness is supplied using magic_churnrand(). @@ -180,58 +180,47 @@ void magic_random_bytes(unsigned char *buf, u32_t buf_len) { } /* - * Return a new random number. + * Return a new 32-bit random number. */ u32_t magic(void) { u32_t new_rand; magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); - return new_rand; } #else /* PPP_MD5_RANDM */ -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ #ifndef LWIP_RAND -static int magic_randomized; /* Set when truely randomized. */ +static int magic_randomized; /* Set when truly randomized. */ #endif /* LWIP_RAND */ static u32_t magic_randomseed; /* Seed used for random number generation. */ - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ - /* * Initialize the random number generator. * * Here we attempt to compute a random number seed but even if * it isn't random, we'll randomize it later. * - * The current method uses the fields from the real time clock, - * the idle process counter, the millisecond counter, and the - * hardware timer tick counter. When this is invoked - * in startup(), then the idle counter and timer values may - * repeat after each boot and the real time clock may not be - * operational. Thus we call it again on the first random - * event. + * The current method uses the jiffies counter. When this is + * invoked at startup the jiffies counter value may repeat + * after each boot. Thus we call it again on the first + * random event. + * + * If LWIP_RAND if available, we do not call srand() as we are + * not going to call rand(). */ void magic_init(void) { magic_randomseed += sys_jiffies(); #ifndef LWIP_RAND - /* Initialize the Borland random number generator. */ + /* Initialize the random number generator. */ srand((unsigned)magic_randomseed); #endif /* LWIP_RAND */ } /* - * magic_init - Initialize the magic number generator. - * * Randomize our random seed value. Here we use the fact that - * this function is called at *truely random* times by the polling + * this function is called at *truly random* times by the polling * and network functions. Here we only get 16 bits of new random * value but we use the previous value to randomize the other 16 * bits. @@ -242,34 +231,37 @@ void magic_randomize(void) { magic_randomized = !0; magic_init(); /* The initialization function also updates the seed. */ - } else { -#endif /* LWIP_RAND */ - magic_randomseed += sys_jiffies(); -#ifndef LWIP_RAND + return; } #endif /* LWIP_RAND */ + magic_randomseed += sys_jiffies(); } /* - * Return a new random number. + * Return a new 32-bit random number. * - * Here we use the Borland rand() function to supply a pseudo random - * number which we make truely random by combining it with our own - * seed which is randomized by truely random events. - * Thus the numbers will be truely random unless there have been no + * Here we use the rand() function to supply a pseudo random + * number which we make truly random by combining it with our own + * seed which is randomized by truly random events. + * Thus the numbers will be truly random unless there have been no * operator or network events in which case it will be pseudo random - * seeded by the real time clock. + * seeded by srand(). + * + * Alternatively, use LWIP_RAND if available, but we do not assume + * it is returning 32 bits of random data because it is probably + * going to be defined to directly return the rand() value. For + * example, LCP magic numbers are 32-bit random values. */ u32_t magic(void) { #ifdef LWIP_RAND - return LWIP_RAND() + magic_randomseed; + return (LWIP_RAND() << 16) + LWIP_RAND() + magic_randomseed; #else /* LWIP_RAND */ return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; #endif /* LWIP_RAND */ } /* - * magic_random_bytes - Fill a buffer with random bytes. + * Fill a buffer with random bytes. */ void magic_random_bytes(unsigned char *buf, u32_t buf_len) { u32_t new_rand, n; diff --git a/src/netif/ppp/magic.h b/src/netif/ppp/magic.h index a165e18..12a002c 100644 --- a/src/netif/ppp/magic.h +++ b/src/netif/ppp/magic.h @@ -94,7 +94,7 @@ extern "C" { void magic_init(void); /* - * Randomize our random seed value. To be called for truely random events + * Randomize our random seed value. To be called for truly random events * such as user operations and network traffic. */ void magic_randomize(void); diff --git a/src/netif/ppp/multilink.c b/src/netif/ppp/multilink.c index 62014e8..795d6b5 100644 --- a/src/netif/ppp/multilink.c +++ b/src/netif/ppp/multilink.c @@ -142,18 +142,18 @@ mp_join_bundle() /* not doing multilink */ if (go->neg_mrru) notice("oops, multilink negotiated only for receive"); - mtu = ho->neg_mru? ho->mru: PPP_MRU; + mtu = ho->neg_mru? ho->mru: PPP_DEFMRU; if (mtu > ao->mru) mtu = ao->mru; if (demand) { /* already have a bundle */ cfg_bundle(0, 0, 0, 0); - netif_set_mtu(pcb, mtu); + ppp_netif_set_mtu(pcb, mtu); return 0; } make_new_bundle(0, 0, 0, 0); set_ifunit(1); - netif_set_mtu(pcb, mtu); + ppp_netif_set_mtu(pcb, mtu); return 0; } @@ -198,7 +198,7 @@ mp_join_bundle() mtu = LWIP_MIN(ho->mrru, ao->mru); if (demand) { cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); - netif_set_mtu(pcb, mtu); + ppp_netif_set_mtu(pcb, mtu); script_setenv("BUNDLE", bundle_id + 7, 1); return 0; } @@ -245,7 +245,7 @@ mp_join_bundle() /* we have to make a new bundle */ make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); set_ifunit(1); - netif_set_mtu(pcb, mtu); + ppp_netif_set_mtu(pcb, mtu); script_setenv("BUNDLE", bundle_id + 7, 1); make_bundle_links(pcb); unlock_db(); diff --git a/src/netif/ppp/ppp.c b/src/netif/ppp/ppp.c index be58553..1cd5958 100644 --- a/src/netif/ppp/ppp.c +++ b/src/netif/ppp/ppp.c @@ -255,6 +255,7 @@ void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { #if PPP_NOTIFY_PHASE void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { + LWIP_ASSERT_CORE_LOCKED(); pcb->notify_phase_cb = notify_phase_cb; notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); } @@ -476,7 +477,6 @@ static err_t ppp_netif_init_cb(struct netif *netif) { #if PPP_IPV6_SUPPORT netif->output_ip6 = ppp_netif_output_ip6; #endif /* PPP_IPV6_SUPPORT */ - netif->flags = NETIF_FLAG_UP; #if LWIP_NETIF_HOSTNAME /* @todo: Initialize interface hostname */ /* netif_set_hostname(netif, "lwip"); */ @@ -674,9 +674,9 @@ ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, vo #endif /* PAP_SUPPORT */ #if CHAP_SUPPORT +#if PPP_SERVER pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; -#if PPP_SERVER pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; #endif /* PPP_SERVER */ #endif /* CHAP_SUPPPORT */ @@ -710,6 +710,9 @@ ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, vo PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); return NULL; } + /* FIXME: user application should be responsible to call netif_set_up(), + * remove it for next release with allowed behavior break */ + netif_set_up(pcb->netif); pcb->link_cb = callbacks; pcb->link_ctx_cb = link_ctx_cb; @@ -776,8 +779,10 @@ void ppp_link_end(ppp_pcb *pcb) { void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { u16_t protocol; #if PPP_DEBUG && PPP_PROTOCOLNAME - const char *pname; + const char *pname; #endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ + LWIP_ASSERT("pcb->phase >= PPP_PHASE_ESTABLISH && pcb->phase <= PPP_PHASE_TERMINATE", + pcb->phase >= PPP_PHASE_ESTABLISH && pcb->phase <= PPP_PHASE_TERMINATE); magic_randomize(); @@ -801,7 +806,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { * Toss all non-LCP packets unless LCP is OPEN. */ if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { - ppp_dbglog("Discarded non-LCP packet when LCP not open"); + ppp_dbglog(("Discarded non-LCP packet when LCP not open")); goto drop; } @@ -824,7 +829,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { || protocol == PPP_EAP #endif /* EAP_SUPPORT */ )) { - ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); + ppp_dbglog(("discarding proto 0x%x in phase %d", protocol, pcb->phase)); goto drop; } @@ -875,7 +880,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { } #endif /* CCP_SUPPORT */ - switch(protocol) { + switch (protocol) { #if PPP_IPV4_SUPPORT case PPP_IP: /* Internet Protocol */ @@ -931,6 +936,10 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { for (i = 0; (protp = protocols[i]) != NULL; ++i) { if (protp->protocol == protocol) { pb = pbuf_coalesce(pb, PBUF_RAW); + if (pb->next != NULL) { + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping (pbuf_coalesce failed), len=%d\n", pcb->netif->num, pb->tot_len)); + goto drop; + } (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); goto out; } @@ -959,18 +968,19 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { #if PPP_PROTOCOLNAME pname = protocol_name(protocol); if (pname != NULL) { - ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + ppp_warn(("Unsupported protocol '%s' (0x%x) received", pname, protocol)); } else #endif /* PPP_PROTOCOLNAME */ - ppp_warn("Unsupported protocol 0x%x received", protocol); + ppp_warn(("Unsupported protocol 0x%x received", protocol)); #endif /* PPP_DEBUG */ - if (pbuf_add_header(pb, sizeof(protocol))) { - PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping (pbuf_add_header failed)\n", pcb->netif->num)); - goto drop; - } - lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); + + if (pbuf_add_header(pb, sizeof(protocol))) { + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping (pbuf_add_header failed)\n", pcb->netif->num)); + goto drop; } - break; + lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); + } + break; } drop: @@ -1027,13 +1037,13 @@ void new_phase(ppp_pcb *pcb, int p) { */ int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { LWIP_UNUSED_ARG(mtu); - /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ + + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num)); if (pcb->link_cb->send_config) { pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); } - PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); return 0; } @@ -1044,11 +1054,12 @@ int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { LWIP_UNUSED_ARG(mru); + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); + if (pcb->link_cb->recv_config) { pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); } - PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); return 0; } @@ -1129,12 +1140,12 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { nsa = dns_getserver(0); ip_addr_set_ip4_u32_val(nsb, ns1); - if (ip_addr_cmp(nsa, &nsb)) { + if (ip_addr_eq(nsa, &nsb)) { dns_setserver(0, IP_ADDR_ANY); } nsa = dns_getserver(1); ip_addr_set_ip4_u32_val(nsb, ns2); - if (ip_addr_cmp(nsa, &nsb)) { + if (ip_addr_eq(nsa, &nsb)) { dns_setserver(1, IP_ADDR_ANY); } return 1; @@ -1313,18 +1324,21 @@ int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { #endif /* DEMAND_SUPPORT */ /* - * netif_set_mtu - set the MTU on the PPP network interface. + * ppp_netif_set_mtu - set the MTU on the PPP network interface. */ -void netif_set_mtu(ppp_pcb *pcb, int mtu) { +void ppp_netif_set_mtu(ppp_pcb *pcb, int mtu) { pcb->netif->mtu = mtu; - PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); +#if PPP_IPV6_SUPPORT && LWIP_ND6_ALLOW_RA_UPDATES + pcb->netif->mtu6 = mtu; +#endif /* PPP_IPV6_SUPPORT && LWIP_ND6_ALLOW_RA_UPDATES */ + PPPDEBUG(LOG_INFO, ("ppp_netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); } /* - * netif_get_mtu - get PPP interface MTU + * ppp_netif_get_mtu - get PPP interface MTU */ -int netif_get_mtu(ppp_pcb *pcb) { +int ppp_netif_get_mtu(ppp_pcb *pcb) { return pcb->netif->mtu; } diff --git a/src/netif/ppp/ppp.h b/src/netif/ppp/ppp.h index 3d73c36..f93747f 100644 --- a/src/netif/ppp/ppp.h +++ b/src/netif/ppp/ppp.h @@ -266,9 +266,9 @@ typedef struct ppp_settings_s { #endif /* PAP_SUPPPORT */ #if CHAP_SUPPORT +#if PPP_SERVER u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ u8_t chap_max_transmits; /* max # times to send challenge */ -#if PPP_SERVER u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ #endif /* PPP_SERVER */ #endif /* CHAP_SUPPPORT */ diff --git a/src/netif/ppp/ppp_impl.h b/src/netif/ppp/ppp_impl.h index 40843d5..2282831 100644 --- a/src/netif/ppp/ppp_impl.h +++ b/src/netif/ppp/ppp_impl.h @@ -60,16 +60,10 @@ extern "C" { /* * Memory used for control packets. * - * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we + * PPP_CTRL_PBUF_UNKNOWN_SIZE is the amount of memory we allocate when we * cannot figure out how much we are going to use before filling the buffer. */ -#if PPP_USE_PBUF_RAM -#define PPP_CTRL_PBUF_TYPE PBUF_RAM -#define PPP_CTRL_PBUF_MAX_SIZE 512 -#else /* PPP_USE_PBUF_RAM */ -#define PPP_CTRL_PBUF_TYPE PBUF_POOL -#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE -#endif /* PPP_USE_PBUF_RAM */ +#define PPP_CTRL_PBUF_UNKNOWN_SIZE 512 /* * The basic PPP frame. @@ -87,10 +81,18 @@ extern "C" { #define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ #define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ +/* + * PPP_DEFMRU: MRU value used prior negotiation and unless negotiated later. + * Must be 1500. + */ +#define PPP_DEFMRU 1500 + /* * Protocol field values. */ +#if PPP_IPV4_SUPPORT #define PPP_IP 0x21 /* Internet Protocol */ +#endif /* PPP_IPV4_SUPPORT */ #if 0 /* UNUSED */ #define PPP_AT 0x29 /* AppleTalk Protocol */ #define PPP_IPX 0x2b /* IPX protocol */ @@ -265,7 +267,7 @@ extern int maxoctets_timeout; /* Timeout for check of octets limit */ #define PPP_OCTETS_DIRECTION_IN 1 #define PPP_OCTETS_DIRECTION_OUT 2 #define PPP_OCTETS_DIRECTION_MAXOVERAL 3 -/* same as previos, but little different on RADIUS side */ +/* same as previous, but little different on RADIUS side */ #define PPP_OCTETS_DIRECTION_MAXSESSION 4 #endif @@ -456,8 +458,8 @@ int sif6down (ppp_pcb *pcb); int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); #endif /* DEMAND_SUPPORt */ -void netif_set_mtu(ppp_pcb *pcb, int mtu); -int netif_get_mtu(ppp_pcb *pcb); +void ppp_netif_set_mtu(ppp_pcb *pcb, int mtu); +int ppp_netif_get_mtu(ppp_pcb *pcb); #if CCP_SUPPORT #if 0 /* unused */ @@ -539,7 +541,7 @@ void update_link_stats(int u); /* Get stats at link termination */ #define BZERO(s, n) memset(s, 0, n) #define BCMP(s1, s2, l) memcmp(s1, s2, l) -#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } +#define PRINTMSG(m, l) { ppp_info(("Remote message: %0.*v", l, m)); } /* * MAKEHEADER - Add Header fields to a packet. @@ -559,7 +561,7 @@ void start_networks(ppp_pcb *pcb); /* start all the network control protos */ void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ #if PPP_AUTH_SUPPORT #if PPP_SERVER -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); +int auth_check_passwd(ppp_pcb *pcb, char *auser, unsigned int userlen, char *apasswd, unsigned int passwdlen, const char **msg, int *msglen); /* check the user name and passwd against configuration */ void auth_peer_fail(ppp_pcb *pcb, int protocol); /* peer failed to authenticate itself */ @@ -614,12 +616,19 @@ int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* spr int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ -void ppp_dbglog(const char *fmt, ...); /* log a debug message */ -void ppp_info(const char *fmt, ...); /* log an informational message */ -void ppp_notice(const char *fmt, ...); /* log a notice-level message */ -void ppp_warn(const char *fmt, ...); /* log a warning message */ -void ppp_error(const char *fmt, ...); /* log an error message */ -void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ +void ppp_dbglog_impl(const char *fmt, ...); /* log a debug message */ +void ppp_info_impl(const char *fmt, ...); /* log an informational message */ +void ppp_notice_impl(const char *fmt, ...); /* log a notice-level message */ +void ppp_warn_impl(const char *fmt, ...); /* log a warning message */ +void ppp_error_impl(const char *fmt, ...); /* log an error message */ +void ppp_fatal_impl(const char *fmt, ...); /* log an error message and die(1) */ +/* wrap all the above functions so they will only be linked when enabled */ +#define ppp_dbglog(x) do { if (LWIP_DEBUG_ENABLED(LOG_DEBUG)) { ppp_dbglog_impl x; }} while(0) +#define ppp_info(x) do { if (LWIP_DEBUG_ENABLED(LOG_INFO)) { ppp_info_impl x; }} while(0) +#define ppp_notice(x) do { if (LWIP_DEBUG_ENABLED(LOG_NOTICE)) { ppp_notice_impl x; }} while(0) +#define ppp_warn(x) do { if (LWIP_DEBUG_ENABLED(LOG_WARNING)) { ppp_warn_impl x; }} while(0) +#define ppp_error(x) do { if (LWIP_DEBUG_ENABLED(LOG_ERR)) { ppp_error_impl x; }} while(0) +#define ppp_fatal(x) do { if (LWIP_DEBUG_ENABLED(LOG_CRITICAL)) { ppp_fatal_impl x; }} while(0) #if PRINTPKT_SUPPORT void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); /* dump packet to debug log if interesting */ @@ -665,11 +674,10 @@ void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); * |. . . * | . . * PPP_PHASE_AUTHENTICATE - * | . . * || . . * PPP_PHASE_NETWORK - * | || . . - * | ||| . + * |||| . . + * || ||| . * PPP_PHASE_RUNNING * | .||||| * | . |||| @@ -685,33 +693,39 @@ void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); * 1 * * If authentication is enabled one timer is necessary during authentication. + * This timer might still be running up to network phase for any necessary + * rechallenge, mostly for PPP server support. * 1 + PPP_AUTH_SUPPORT * * If ECP is enabled one timer is necessary before IPCP and/or IP6CP, one more * is necessary if CCP is enabled (only with MPPE support but we don't care much * up to this detail level). - * 1 + ECP_SUPPORT + CCP_SUPPORT + * 1 + PPP_AUTH_SUPPORT + ECP_SUPPORT + CCP_SUPPORT * * If CCP is enabled it might consume a timer during IPCP or IP6CP, thus - * we might use IPCP, IP6CP and CCP timers simultaneously. - * 1 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT + * we might use AUTH, IPCP, IP6CP and CCP timers simultaneously. + * 1 + PPP_AUTH_SUPPORT + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT * * When entering running phase, IPCP or IP6CP is still running. If idle time limit * is enabled one more timer is necessary. Same for max connect time and max * octets features. Furthermore CCP RACK might be used past this point. * 1 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT -1 + PPP_IDLETIMELIMIT + PPP_MAXCONNECT + MAXOCTETS + CCP_SUPPORT * - * IPv4 or IPv6 must be enabled, therefore we don't need to take care the authentication - * and the CCP + ECP case, thus reducing overall complexity. - * 1 + LWIP_MAX(PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT, PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT -1 + PPP_IDLETIMELIMIT + PPP_MAXCONNECT + MAXOCTETS + CCP_SUPPORT) + * Then the maximum number of simultaneously running timers is given by: + * 1 + MAX(PPP_AUTH_SUPPORT + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT, + * PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT -1 + PPP_IDLETIMELIMIT + PPP_MAXCONNECT + MAXOCTETS + CCP_SUPPORT) * - * We don't support PPP_IDLETIMELIMIT + PPP_MAXCONNECT + MAXOCTETS features - * and adding those defines to ppp_opts.h just for having the value always - * defined to 0 isn't worth it. - * 1 + LWIP_MAX(PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT, PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT -1 + CCP_SUPPORT) + * We don't support ECP_SUPPORT + PPP_IDLETIMELIMIT + PPP_MAXCONNECT + MAXOCTETS features + * and adding those defines to ppp_opts.h just for having the value always defined to 0 + * is not worth it, thus reducing the overall complexity. + * 1 + MAX(PPP_AUTH_SUPPORT + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT, + * PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT -1 + CCP_SUPPORT) * - * Thus, the following is enough for now. - * 1 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT + * PPP_AUTH_SUPPORT is not available in ppp_opts.h because it is defined later in ppp.h, + * but we do not need to be that picky about the real number of simultaneously running + * timers so we just set the base number of timeouts to 2, thus the following is enough + * for now. + * 2 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT */ #ifdef __cplusplus diff --git a/src/netif/ppp/ppp_opts.h b/src/netif/ppp/ppp_opts.h index 479a006..be22c4c 100644 --- a/src/netif/ppp/ppp_opts.h +++ b/src/netif/ppp/ppp_opts.h @@ -95,7 +95,7 @@ * timers analysis. */ #ifndef PPP_NUM_TIMEOUTS_PER_PCB -#define PPP_NUM_TIMEOUTS_PER_PCB (1 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT) +#define PPP_NUM_TIMEOUTS_PER_PCB (2 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT) #endif /* The number of sys_timeouts required for the PPP module */ @@ -184,20 +184,6 @@ #define PPP_NOTIFY_PHASE 0 #endif -/** - * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. - * - * Memory allocated must be single buffered for PPP to works, it requires pbuf - * that are not going to be chained when allocated. This requires setting - * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. - * - * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous - * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. - */ -#ifndef PPP_USE_PBUF_RAM -#define PPP_USE_PBUF_RAM 0 -#endif - /** * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS */ @@ -311,9 +297,11 @@ /** * VJ_SUPPORT==1: Support VJ header compression. + * + * BEWARE: It is known to be broken when built with some compiler optimizations enabled. */ #ifndef VJ_SUPPORT -#define VJ_SUPPORT 1 +#define VJ_SUPPORT 0 #endif /* VJ compression is only supported for TCP over IPv4 over PPPoS. */ #if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP @@ -507,28 +495,33 @@ */ /** - * PPP_MRU: Default MRU + * PPP_MRU: MRU value we want to negotiate (peer MTU) + * + * It only affects PPPoS because PPPoE value is derived from the + * Ethernet interface MTU and PPPoL2TP have a separate setting. */ #ifndef PPP_MRU #define PPP_MRU 1500 #endif /** - * PPP_DEFMRU: Default MRU to try - */ -#ifndef PPP_DEFMRU -#define PPP_DEFMRU 1500 -#endif - -/** - * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) + * PPP_MAXMRU: Normally limit peer MRU to this + * + * This is the upper limit value to which we set our interface MTU. + * If the peer sends a larger number, we will just ignore it as we + * are not required to maximize the use of the peer capacity. + * + * It only affects PPPoS because PPPoE value is derived from the + * Ethernet interface MTU and PPPoL2TP have a separate setting. */ #ifndef PPP_MAXMRU #define PPP_MAXMRU 1500 #endif /** - * PPP_MINMRU: No MRUs below this + * PPP_MINMRU: No peer MRUs below this + * + * Peer must be able to receive at least our minimum MTU. */ #ifndef PPP_MINMRU #define PPP_MINMRU 128 diff --git a/src/netif/ppp/pppoe.c b/src/netif/ppp/pppoe.c index 971b36b..9e4f346 100644 --- a/src/netif/ppp/pppoe.c +++ b/src/netif/ppp/pppoe.c @@ -132,7 +132,7 @@ static void pppoe_clear_softc(struct pppoe_softc *, const char *); /* internal timeout handling */ static void pppoe_timeout(void *); -/* sending actual protocol controll packets */ +/* sending actual protocol control packets */ static err_t pppoe_send_padi(struct pppoe_softc *); static err_t pppoe_send_padr(struct pppoe_softc *); #ifdef PPPOE_SERVER @@ -175,12 +175,29 @@ ppp_pcb *pppoe_create(struct netif *pppif, { ppp_pcb *ppp; struct pppoe_softc *sc; -#if !PPPOE_SCNAME_SUPPORT +#if PPPOE_SCNAME_SUPPORT + size_t l; +#else /* PPPOE_SCNAME_SUPPORT */ LWIP_UNUSED_ARG(service_name); LWIP_UNUSED_ARG(concentrator_name); -#endif /* !PPPOE_SCNAME_SUPPORT */ +#endif /* PPPOE_SCNAME_SUPPORT */ LWIP_ASSERT_CORE_LOCKED(); +#if PPPOE_SCNAME_SUPPORT + /* + * Check that service_name and concentrator_name strings length will + * not trigger integer overflows when computing packets length. + */ + l = strlen(service_name); + if (l > 1024) { + return NULL; + } + l = strlen(concentrator_name); + if (l > 1024) { + return NULL; + } +#endif /* PPPOE_SCNAME_SUPPORT */ + sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); if (sc == NULL) { return NULL; @@ -393,6 +410,10 @@ pppoe_disc_input(struct netif *netif, struct pbuf *pb) } pb = pbuf_coalesce(pb, PBUF_RAW); + if (pb->next != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: pbuf_coalesce failed: %d\n", pb->tot_len)); + goto done; + } ethhdr = (struct eth_hdr *)pb->payload; @@ -753,20 +774,20 @@ pppoe_send_padi(struct pppoe_softc *sc) { struct pbuf *pb; u8_t *p; - int len; + size_t len; #if PPPOE_SCNAME_SUPPORT - int l1 = 0, l2 = 0; /* XXX: gcc */ + size_t l1 = 0, l2 = 0; /* XXX: gcc */ #endif /* PPPOE_SCNAME_SUPPORT */ /* calculate length of frame (excluding ethernet header + pppoe header) */ len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ #if PPPOE_SCNAME_SUPPORT if (sc->sc_service_name != NULL) { - l1 = (int)strlen(sc->sc_service_name); + l1 = strlen(sc->sc_service_name); len += l1; } if (sc->sc_concentrator_name != NULL) { - l2 = (int)strlen(sc->sc_concentrator_name); + l2 = strlen(sc->sc_concentrator_name); len += 2 + 2 + l2; } #endif /* PPPOE_SCNAME_SUPPORT */ @@ -848,7 +869,6 @@ pppoe_timeout(void *arg) /* initialize for quick retry mode */ retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); if ((err = pppoe_send_padi(sc)) != 0) { - sc->sc_padi_retried--; PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ } @@ -869,7 +889,6 @@ pppoe_timeout(void *arg) return; } if ((err = pppoe_send_padr(sc)) != 0) { - sc->sc_padr_retried--; PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ } diff --git a/src/netif/ppp/pppoe.h b/src/netif/ppp/pppoe.h index 8994d38..b5f7ed1 100644 --- a/src/netif/ppp/pppoe.h +++ b/src/netif/ppp/pppoe.h @@ -128,7 +128,7 @@ PACK_STRUCT_END #define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ #define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ #define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ -#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* generic error */ #define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ #define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ diff --git a/src/netif/ppp/pppol2tp.c b/src/netif/ppp/pppol2tp.c index 4c4557f..2a9a9b1 100644 --- a/src/netif/ppp/pppol2tp.c +++ b/src/netif/ppp/pppol2tp.c @@ -172,6 +172,9 @@ static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { LWIP_UNUSED_ARG(ppp); #endif /* MIB2_STATS */ + /* skip address & flags */ + pbuf_remove_header(p, 2); + ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); if(!ph) { LINK_STATS_INC(link.memerr); @@ -353,7 +356,7 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const goto free_and_return; } - if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { + if (!ip_addr_eq(&l2tp->remote_ip, addr)) { goto free_and_return; } @@ -440,7 +443,7 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", - len, tunnel_id, session_id, ns, nr)); + p->tot_len, tunnel_id, session_id, ns, nr)); /* Control packet */ if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { @@ -463,8 +466,16 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const /* * skip address & flags if necessary * - * RFC 2661 does not specify whether the PPP frame in the L2TP payload should - * have a HDLC header or not. We handle both cases for compatibility. + * RFC 2661 (L2TPv2) does not specify whether the PPP frame in the L2TP payload + * should have a HDLC header or not, both behaviors are seen in the wild. + * + * On the other hand, L2TPv3 draft-ietf-l2tpext-l2tp-ppp versions 00 and 01 say + * it must be included, versions 02 to 05 say it must be omitted, and versions + * 06 and onwards say it should be omitted so it changed along the path when + * L2TPv3 was designed. Latest versions state that receivers must handle both + * cases. + * + * We handle both cases for compatibility. */ if (p->len >= 2) { GETSHORT(hflags, inp); @@ -530,6 +541,11 @@ static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, str l2tp->peer_ns = ns+1; p = pbuf_coalesce(p, PBUF_RAW); + if (p->next != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: pbuf_coalesce failed: %d\n", p->tot_len)); + return; + } + inp = (u8_t*)p->payload; /* Decode AVPs */ while (p->len > 0) { @@ -749,7 +765,6 @@ static void pppol2tp_timeout(void *arg) { retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { - l2tp->sccrq_retried--; PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ } @@ -765,7 +780,6 @@ static void pppol2tp_timeout(void *arg) { PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); if ((s16_t)(l2tp->peer_nr - l2tp->our_ns) < 0) { /* the SCCCN was not acknowledged */ if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { - l2tp->icrq_retried--; PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); @@ -773,7 +787,6 @@ static void pppol2tp_timeout(void *arg) { } } if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { - l2tp->icrq_retried--; PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ } @@ -788,7 +801,6 @@ static void pppol2tp_timeout(void *arg) { } PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { - l2tp->iccn_retried--; PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */ } diff --git a/src/netif/ppp/pppos.c b/src/netif/ppp/pppos.c index dff0255..8847536 100644 --- a/src/netif/ppp/pppos.c +++ b/src/netif/ppp/pppos.c @@ -207,10 +207,9 @@ pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) err_t err; LWIP_UNUSED_ARG(ppp); - /* Grab an output buffer. Using PBUF_POOL here for tx is ok since the pbuf - gets freed by 'pppos_output_last' before this function returns and thus - cannot starve rx. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + /* Grab an output buffer. Assume PBUF_POOL_BUFSIZE is an acceptable + * chunk size for Tx as well. */ + nb = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_RAM); if (nb == NULL) { PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); LINK_STATS_INC(link.memerr); @@ -220,6 +219,8 @@ pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) return ERR_MEM; } + /* Empty the buffer */ + nb->len = 0; /* Set nb->tot_len to actual payload length */ nb->tot_len = p->len; @@ -258,10 +259,9 @@ pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) err_t err; LWIP_UNUSED_ARG(ppp); - /* Grab an output buffer. Using PBUF_POOL here for tx is ok since the pbuf - gets freed by 'pppos_output_last' before this function returns and thus - cannot starve rx. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + /* Grab an output buffer. Assume PBUF_POOL_BUFSIZE is an acceptable + * chunk size for Tx as well. */ + nb = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_RAM); if (nb == NULL) { PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); LINK_STATS_INC(link.memerr); @@ -270,6 +270,8 @@ pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) return ERR_MEM; } + /* Empty the buffer */ + nb->len = 0; /* Set nb->tot_len to actual payload length */ nb->tot_len = pb->tot_len; @@ -420,7 +422,7 @@ pppos_destroy(ppp_pcb *ppp, void *ctx) * @param l length of received data */ err_t -pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) +pppos_input_tcpip(ppp_pcb *ppp, const void *s, int l) { struct pbuf *p; err_t err; @@ -445,7 +447,7 @@ err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { LWIP_ASSERT_CORE_LOCKED(); for (n = p; n; n = n->next) { - pppos_input(ppp, (u8_t*)n->payload, n->len); + pppos_input(ppp, n->payload, n->len); } pbuf_free(p); return ERR_OK; @@ -475,10 +477,11 @@ PACK_STRUCT_END * @param l length of received data */ void -pppos_input(ppp_pcb *ppp, u8_t *s, int l) +pppos_input(ppp_pcb *ppp, const void *s, int l) { pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; struct pbuf *next_pbuf; + const u8_t *s_u8 = (const u8_t *)s; u8_t cur_char; u8_t escaped; PPPOS_DECL_PROTECT(lev); @@ -486,22 +489,24 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) LWIP_ASSERT_CORE_LOCKED(); #endif + /* Don't even bother parsing data if we are disconnected. + * Added to that, ppp_input must never be called if the upper layer is down. + */ + PPPOS_PROTECT(lev); + if (!pppos->open) { + PPPOS_UNPROTECT(lev); + return; + } + PPPOS_UNPROTECT(lev); + PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); while (l-- > 0) { - cur_char = *s++; + cur_char = *s_u8++; PPPOS_PROTECT(lev); - /* ppp_input can disconnect the interface, we need to abort to prevent a memory - * leak if there are remaining bytes because pppos_connect and pppos_listen - * functions expect input buffer to be free. Furthermore there are no real - * reason to continue reading bytes if we are disconnected. - */ - if (!pppos->open) { - PPPOS_UNPROTECT(lev); - return; - } escaped = ESCAPE_P(pppos->in_accm, cur_char); PPPOS_UNPROTECT(lev); + /* Handle special characters. */ if (escaped) { /* Check for escape sequences. */ @@ -531,6 +536,12 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ LINK_STATS_INC(link.chkerr); pppos_input_drop(pppos); + } else if (!pppos->in_tail) { + PPPDEBUG(LOG_INFO, + ("pppos_input[%d]: Dropping null in_tail\n", + ppp->netif->num)); + LINK_STATS_INC(link.drop); + pppos_input_drop(pppos); /* Otherwise it's a good packet so pass it on. */ } else { struct pbuf *inp; @@ -558,7 +569,16 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) pppos->in_tail = NULL; #if IP_FORWARD || LWIP_IPV6_FORWARD /* hide the room for Ethernet forwarding header */ - pbuf_remove_header(inp, PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN); + if (0 +#if PPP_IPV4_SUPPORT + || pppos->in_protocol == PPP_IP +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || pppos->in_protocol == PPP_IPV6 +#endif /* PPP_IPV6_SUPPORT */ + ) { + pbuf_remove_header(inp, PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN); + } #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ #if PPP_INPROC_IRQ_SAFE if(tcpip_try_callback(pppos_input_callback, inp) != ERR_OK) { @@ -569,6 +589,14 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) } #else /* PPP_INPROC_IRQ_SAFE */ ppp_input(ppp, inp); + /* ppp_input can disconnect the interface, we need to abort to prevent a memory + * leak if there are remaining bytes because pppos_connect and pppos_listen + * functions expect input buffer to be free. Furthermore there are no real + * reason to continue reading bytes if we are disconnected. + */ + if (!pppos->open) { + break; + } #endif /* PPP_INPROC_IRQ_SAFE */ } @@ -591,50 +619,24 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) } /* Process character relative to current state. */ - switch(pppos->in_state) { - case PDIDLE: /* Idle state - waiting. */ - /* Drop the character if it's not 0xff - * we would have processed a flag character above. */ - if (cur_char != PPP_ALLSTATIONS) { - break; - } - /* no break */ - /* Fall through */ - - case PDSTART: /* Process start flag. */ - /* Prepare for a new packet. */ - pppos->in_fcs = PPP_INITFCS; - /* no break */ - /* Fall through */ - + switch (pppos->in_state) { + case PDIDLE: /* Idle state - wait for flag character. */ + break; case PDADDRESS: /* Process address field. */ if (cur_char == PPP_ALLSTATIONS) { pppos->in_state = PDCONTROL; break; } - /* no break */ - /* Else assume compressed address and control fields so * fall through to get the protocol... */ /* Fall through */ case PDCONTROL: /* Process control field. */ - /* If we don't get a valid control code, restart. */ if (cur_char == PPP_UI) { pppos->in_state = PDPROTOCOL1; break; } - /* no break */ - -#if 0 - else { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); - pppos->in_state = PDSTART; - } -#endif /* Fall through */ - - case PDPROTOCOL1: /* Process protocol field 1. */ + case PDPROTOCOL1: /* Process protocol field 1. */ /* If the lower bit is set, this is the end of the protocol * field. */ if (cur_char & 1) { @@ -654,12 +656,37 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { u16_t pbuf_alloc_len; if (pppos->in_tail != NULL) { + u16_t mru; pppos->in_tail->tot_len = pppos->in_tail->len; if (pppos->in_tail != pppos->in_head) { pbuf_cat(pppos->in_head, pppos->in_tail); /* give up the in_tail reference now */ pppos->in_tail = NULL; } + /* Compute MRU including headers length. If smaller packets are + * requested, we must still be able to receive packets of the + * default MRU for control packets. */ + mru = LWIP_MAX(PPP_MRU, PPP_DEFMRU) + /* Add 10% more. We only want to avoid filling all PBUFs with garbage, + * we don't have to be pedantic. */ + + LWIP_MAX(PPP_MRU, PPP_DEFMRU)/10 +#if IP_FORWARD || LWIP_IPV6_FORWARD + + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ +#if PPP_INPROC_IRQ_SAFE + + sizeof(struct pppos_input_header) +#endif /* PPP_INPROC_IRQ_SAFE */ + + sizeof(pppos->in_protocol); + if (pppos->in_head->tot_len > mru) { + /* Packet too big. Drop the input packet and let the + * higher layers deal with it. Continue processing + * received characters in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: packet too big, max_len=%d, dropping packet\n", ppp->netif->num, mru)); + LINK_STATS_INC(link.lenerr); + pppos_input_drop(pppos); + pppos->in_state = PDIDLE; /* Wait for flag character. */ + break; + } } /* If we haven't started a packet, we need a packet header. */ pbuf_alloc_len = 0; @@ -668,7 +695,14 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header * space to be forwarded (to Ethernet for example). */ - if (pppos->in_head == NULL) { + if (pppos->in_head == NULL && (0 +#if PPP_IPV4_SUPPORT + || pppos->in_protocol == PPP_IP +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || pppos->in_protocol == PPP_IPV6 +#endif /* PPP_IPV6_SUPPORT */ + )) { pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; } #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ @@ -676,11 +710,11 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) if (next_pbuf == NULL) { /* No free buffers. Drop the input packet and let the * higher layers deal with it. Continue processing - * the received pbuf chain in case a new packet starts. */ + * received characters in case a new packet starts. */ PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); LINK_STATS_INC(link.memerr); pppos_input_drop(pppos); - pppos->in_state = PDSTART; /* Wait for flag sequence. */ + pppos->in_state = PDIDLE; /* Wait for flag character. */ break; } if (pppos->in_head == NULL) { @@ -716,10 +750,21 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l) static void pppos_input_callback(void *arg) { struct pbuf *pb = (struct pbuf*)arg; ppp_pcb *ppp; + pppos_pcb *pppos; ppp = ((struct pppos_input_header*)pb->payload)->ppp; if(pbuf_remove_header(pb, sizeof(struct pppos_input_header))) { - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); + goto drop; + } + + /* A previous call to ppp_input might have disconnected the session + * while there were still packets in flight in the tcpip mailbox. + * Drop incoming packets because ppp_input must never be called if + * the upper layer is down. + */ + pppos = (pppos_pcb *)ppp->link_ctx_cb; + if (!pppos->open) { goto drop; } @@ -830,7 +875,7 @@ pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t a * Sure we don't quite fill the buffer if the character doesn't * get escaped but is one character worth complicating this? */ if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { - u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); + u32_t l = pppos->output_cb(pppos->ppp, nb->payload, nb->len, pppos->ppp->ctx_cb); if (l != nb->len) { return ERR_IF; } @@ -869,7 +914,7 @@ pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) /* Send remaining buffer if not empty */ if (nb->len > 0) { - u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); + u32_t l = pppos->output_cb(ppp, nb->payload, nb->len, ppp->ctx_cb); if (l != nb->len) { err = ERR_IF; goto failed; diff --git a/src/netif/ppp/pppos.h b/src/netif/ppp/pppos.h index 380a965..f587498 100644 --- a/src/netif/ppp/pppos.h +++ b/src/netif/ppp/pppos.h @@ -50,7 +50,6 @@ extern "C" { * completed. */ enum { PDIDLE = 0, /* Idle state - waiting. */ - PDSTART, /* Process start flag. */ PDADDRESS, /* Process address field. */ PDCONTROL, /* Process control field. */ PDPROTOCOL1, /* Process protocol field 1. */ @@ -59,7 +58,7 @@ enum { }; /* PPPoS serial output callback function prototype */ -typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); +typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, const void *data, u32_t len, void *ctx); /* * Extended asyncmap - allows any character to be escaped. @@ -103,11 +102,11 @@ ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, #if !NO_SYS && !PPP_INPROC_IRQ_SAFE /* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ -err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); +err_t pppos_input_tcpip(ppp_pcb *ppp, const void *s, int l); #endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ /* PPP over Serial: this is the input function to be called for received data. */ -void pppos_input(ppp_pcb *ppp, u8_t* data, int len); +void pppos_input(ppp_pcb *ppp, const void* data, int len); /* diff --git a/src/netif/ppp/upap.c b/src/netif/ppp/upap.c index 3b2399d..c8cd394 100644 --- a/src/netif/ppp/upap.c +++ b/src/netif/ppp/upap.c @@ -206,7 +206,7 @@ static void upap_timeout(void *arg) { if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { /* give up in disgust */ - ppp_error("No response to PAP authenticate-requests"); + ppp_error(("No response to PAP authenticate-requests")); pcb->upap.us_clientstate = UPAPCS_BADAUTH; auth_withpeer_fail(pcb, PPP_PAP); return; @@ -286,12 +286,12 @@ static void upap_lowerdown(ppp_pcb *pcb) { static void upap_protrej(ppp_pcb *pcb) { if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { - ppp_error("PAP authentication failed due to protocol-reject"); + ppp_error(("PAP authentication failed due to protocol-reject")); auth_withpeer_fail(pcb, PPP_PAP); } #if PPP_SERVER if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { - ppp_error("PAP authentication of peer failed (protocol-reject)"); + ppp_error(("PAP authentication of peer failed (protocol-reject)")); auth_peer_fail(pcb, PPP_PAP); } #endif /* PPP_SERVER */ @@ -439,11 +439,11 @@ static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { if (retcode == UPAP_AUTHACK) { pcb->upap.us_serverstate = UPAPSS_OPEN; - ppp_notice("PAP peer authentication succeeded for %q", rhostname); + ppp_notice(("PAP peer authentication succeeded for %q", rhostname)); auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); } else { pcb->upap.us_serverstate = UPAPSS_BADAUTH; - ppp_warn("PAP peer authentication failed for %q", rhostname); + ppp_warn(("PAP peer authentication failed for %q", rhostname)); auth_peer_fail(pcb, PPP_PAP); } @@ -481,6 +481,7 @@ static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { } } + UNTIMEOUT(upap_timeout, pcb); pcb->upap.us_clientstate = UPAPCS_OPEN; auth_withpeer_success(pcb, PPP_PAP, 0); @@ -516,9 +517,10 @@ static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { } } + UNTIMEOUT(upap_timeout, pcb); pcb->upap.us_clientstate = UPAPCS_BADAUTH; - ppp_error("PAP authentication failed"); + ppp_error(("PAP authentication failed")); auth_withpeer_fail(pcb, PPP_PAP); } @@ -533,7 +535,7 @@ static void upap_sauthreq(ppp_pcb *pcb) { outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + pcb->upap.us_userlen + pcb->upap.us_passwdlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { @@ -570,7 +572,7 @@ static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, in int outlen; outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PBUF_RAM); if(NULL == p) return; if(p->tot_len != p->len) { diff --git a/src/netif/ppp/utils.c b/src/netif/ppp/utils.c index f1366da..99a5fb1 100644 --- a/src/netif/ppp/utils.c +++ b/src/netif/ppp/utils.c @@ -629,7 +629,7 @@ static void ppp_log_write(int level, char *buf) { /* * ppp_fatal - log an error message and die horribly. */ -void ppp_fatal(const char *fmt, ...) { +void ppp_fatal_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -642,7 +642,7 @@ void ppp_fatal(const char *fmt, ...) { /* * ppp_error - log an error message. */ -void ppp_error(const char *fmt, ...) { +void ppp_error_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -656,7 +656,7 @@ void ppp_error(const char *fmt, ...) { /* * ppp_warn - log a warning message. */ -void ppp_warn(const char *fmt, ...) { +void ppp_warn_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -667,7 +667,7 @@ void ppp_warn(const char *fmt, ...) { /* * ppp_notice - log a notice-level message. */ -void ppp_notice(const char *fmt, ...) { +void ppp_notice_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -678,7 +678,7 @@ void ppp_notice(const char *fmt, ...) { /* * ppp_info - log an informational message. */ -void ppp_info(const char *fmt, ...) { +void ppp_info_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -689,7 +689,7 @@ void ppp_info(const char *fmt, ...) { /* * ppp_dbglog - log a debug message. */ -void ppp_dbglog(const char *fmt, ...) { +void ppp_dbglog_impl(const char *fmt, ...) { va_list pvar; va_start(pvar, fmt); @@ -724,7 +724,7 @@ void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { return; } - ppp_dbglog("%s %P", tag, p, len); + ppp_dbglog(("%s %P", tag, p, len)); } #endif /* PRINTPKT_SUPPORT */ @@ -788,9 +788,9 @@ lock(dev) } if (result > 0) - ppp_notice("Device %s is locked by pid %d", dev, result); + ppp_notice(("Device %s is locked by pid %d", dev, result)); else - ppp_error("Can't create lock file %s", lock_file); + ppp_error(("Can't create lock file %s", lock_file)); return -1; #else /* LOCKLIB */ @@ -802,11 +802,11 @@ lock(dev) struct stat sbuf; if (stat(dev, &sbuf) < 0) { - ppp_error("Can't get device number for %s: %m", dev); + ppp_error(("Can't get device number for %s: %m", dev)); return -1; } if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { - ppp_error("Can't lock %s: not a character device", dev); + ppp_error(("Can't lock %s: not a character device", dev)); return -1; } ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", @@ -833,7 +833,7 @@ lock(dev) while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { if (errno != EEXIST) { - ppp_error("Can't create lock file %s: %m", lock_file); + ppp_error(("Can't create lock file %s: %m", lock_file)); break; } @@ -842,7 +842,7 @@ lock(dev) if (fd < 0) { if (errno == ENOENT) /* This is just a timing problem. */ continue; - ppp_error("Can't open existing lock file %s: %m", lock_file); + ppp_error(("Can't open existing lock file %s: %m", lock_file)); break; } #ifndef LOCK_BINARY @@ -853,7 +853,7 @@ lock(dev) close(fd); fd = -1; if (n <= 0) { - ppp_error("Can't read pid from lock file %s", lock_file); + ppp_error(("Can't read pid from lock file %s", lock_file)); break; } @@ -867,12 +867,12 @@ lock(dev) if (pid == 0 || (kill(pid, 0) == -1 && errno == ESRCH)) { if (unlink (lock_file) == 0) { - ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); + ppp_notice(("Removed stale lock on %s (pid %d)", dev, pid)); continue; } - ppp_warn("Couldn't remove stale lock on %s", dev); + ppp_warn(("Couldn't remove stale lock on %s", dev)); } else - ppp_notice("Device %s is locked by pid %d", dev, pid); + ppp_notice(("Device %s is locked by pid %d", dev, pid)); break; } @@ -919,7 +919,7 @@ relock(pid) return -1; fd = open(lock_file, O_WRONLY, 0); if (fd < 0) { - ppp_error("Couldn't reopen lock file %s: %m", lock_file); + ppp_error(("Couldn't reopen lock file %s: %m", lock_file)); lock_file[0] = 0; return -1; } diff --git a/src/netif/ppp/vj.c b/src/netif/ppp/vj.c index 3fecba6..7b6f8ea 100644 --- a/src/netif/ppp/vj.c +++ b/src/netif/ppp/vj.c @@ -15,7 +15,7 @@ * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: * Initial distribution. @@ -218,8 +218,8 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) * again & we don't have to do any reordering if it's used. */ INCR(vjs_packets); - if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + if (!ip4_addr_eq(&ip->src, &cs->cs_ip.src) + || !ip4_addr_eq(&ip->dest, &cs->cs_ip.dest) || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { /* * Wasn't the first -- search for it. @@ -239,8 +239,8 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) do { lcs = cs; cs = cs->cs_next; INCR(vjs_searches); - if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + if (ip4_addr_eq(&ip->src, &cs->cs_ip.src) + && ip4_addr_eq(&ip->dest, &cs->cs_ip.dest) && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { goto found; } @@ -409,7 +409,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) hlen -= deltaS + 4; if (pbuf_remove_header(np, hlen)){ /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); } cp = (u8_t*)np->payload; *cp++ = (u8_t)(changes | NEW_C); @@ -418,7 +418,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) hlen -= deltaS + 3; if (pbuf_remove_header(np, hlen)) { /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); } cp = (u8_t*)np->payload; *cp++ = (u8_t)changes; @@ -621,7 +621,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) /* Remove the compressed header and prepend the uncompressed header. */ if (pbuf_remove_header(n0, vjlen)) { /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); goto bad; } @@ -644,7 +644,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) if (pbuf_remove_header(np, cs->cs_hlen)) { /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_remove_header failed\n", 0); + LWIP_ASSERT("pbuf_remove_header failed", 0); goto bad; } diff --git a/src/netif/ppp/vj.h b/src/netif/ppp/vj.h index 77d9976..a9ba786 100644 --- a/src/netif/ppp/vj.h +++ b/src/netif/ppp/vj.h @@ -16,7 +16,7 @@ * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: * - Initial distribution. @@ -53,7 +53,7 @@ extern "C" { * * There are 5 numbers which can change (they are always inserted * in the following order): TCP urgent pointer, window, - * acknowlegement, sequence number and IP ID. (The urgent pointer + * acknowledgement, sequence number and IP ID. (The urgent pointer * is different from the others in that its value is sent, not the * change in value.) Since typical use of SLIP links is biased * toward small packets (see comments on MTU/MSS below), changes diff --git a/src/netif/slipif.c b/src/netif/slipif.c index 9b175dc..c8e4eb3 100644 --- a/src/netif/slipif.c +++ b/src/netif/slipif.c @@ -46,12 +46,12 @@ * This is an arch independent SLIP netif. The specific serial hooks must be * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send * - * Usage: This netif can be used in three ways:\n - * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() - * until data is received.\n - * 2) In your main loop, call slipif_poll() to check for new RX bytes, - * completed packets are fed into netif->input().\n - * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * Usage: This netif can be used in three ways: + * 1. For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2. In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3. Call slipif_received_byte[s]() from your serial RX ISR and * slipif_process_rxqueue() from your main loop. ISR level decodes * packets and puts completed packets on a queue which is fed into * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for diff --git a/src/netif/slipif.h b/src/netif/slipif.h index 65ba31f..46d2010 100644 --- a/src/netif/slipif.h +++ b/src/netif/slipif.h @@ -84,4 +84,3 @@ void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); #endif #endif /* LWIP_HDR_NETIF_SLIPIF_H */ - diff --git a/src/system/OS/sys_arch.c b/src/system/OS/sys_arch.c index f7e3ff0..5b98e7b 100644 --- a/src/system/OS/sys_arch.c +++ b/src/system/OS/sys_arch.c @@ -36,6 +36,7 @@ #include "lwip/sys.h" #include "lwip/mem.h" #include "lwip/stats.h" +#include "lwip/tcpip.h" #if !NO_SYS @@ -45,6 +46,42 @@ int errno; #endif +#if (__ARM_ARCH_7A__ == 1U) +/* CPSR mode bitmasks */ +#define CPSR_MODE_USER 0x10U +#define CPSR_MODE_SYSTEM 0x1FU + +#define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM)) +#else +#define IS_IRQ_MODE() (__get_IPSR() != 0U) +#endif + +/* Enables multithreading check functions in this port. + + For this to work, in your lwipopts.h file, you need to set this flag to 1, + define LWIP_ASSERT_CORE_LOCKED() and LWIP_MARK_TCPIP_THREAD() macros, + point them to functions sys_check_core_locking() and sys_mark_tcpip_thread() + respectively and add the functions prototypes. + + If you use LWIP_TCPIP_CORE_LOCKING, you also have to define LOCK_TCPIP_CORE() + and UNLOCK_TCPIP_CORE() macros, point them to functions sys_lock_tcpip_core() + and sys_unlock_tcpip_core() respectively and add the functions prototypes. +*/ +#ifndef LWIP_CHECK_MULTITHREADING +#define LWIP_CHECK_MULTITHREADING 0 +#endif /* LWIP_CHECK_MULTITHREADING */ + +#if LWIP_CHECK_MULTITHREADING +#if LWIP_TCPIP_CORE_LOCKING +/* Flag the core lock held. A counter for recursive locks. */ +static u8_t lwip_core_lock_count; +/* Mark the current core lock holder. */ +static osThreadId_t lwip_core_lock_holder_thread; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +/* Mark the tcpip thread. */ +static osThreadId_t lwip_tcpip_thread; +#endif /* LWIP_CHECK_MULTITHREADING */ + /*-----------------------------------------------------------------------------------*/ // Creates an empty mailbox. err_t sys_mbox_new(sys_mbox_t *mbox, int size) @@ -295,12 +332,17 @@ void sys_sem_set_invalid(sys_sem_t *sem) } /*-----------------------------------------------------------------------------------*/ +/* Attributes to support recursive Mutex. */ +const osMutexAttr_t Mutex_attributes = { + .attr_bits = osMutexRecursive, +}; + osMutexId_t lwip_sys_mutex; // Initialize sys arch void sys_init(void) { - lwip_sys_mutex = osMutexNew(NULL); + lwip_sys_mutex = osMutexNew(&Mutex_attributes); } /*-----------------------------------------------------------------------------------*/ /* Mutexes*/ @@ -310,7 +352,7 @@ void sys_init(void) /* Create a new mutex*/ err_t sys_mutex_new(sys_mutex_t *mutex) { - *mutex = osMutexNew(NULL); + *mutex = osMutexNew(&Mutex_attributes); if(*mutex == NULL) { @@ -410,4 +452,62 @@ void sys_arch_unprotect(sys_prot_t pval) osMutexRelease(lwip_sys_mutex); } +/*-----------------------------------------------------------------------------------*/ +#if LWIP_CHECK_MULTITHREADING +#if LWIP_TCPIP_CORE_LOCKING +/* Lock the lwip core, mark the current core lock holder and the lock count. */ +void sys_lock_tcpip_core(void) +{ + sys_mutex_lock(&lock_tcpip_core); + if (lwip_core_lock_count == 0) { + lwip_core_lock_holder_thread = osThreadGetId(); + } + lwip_core_lock_count++; +} + +/* Unlock the lwip core. */ +void sys_unlock_tcpip_core(void) +{ + lwip_core_lock_count--; + if (lwip_core_lock_count == 0) { + lwip_core_lock_holder_thread = 0; + } + sys_mutex_unlock(&lock_tcpip_core); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/* Mark the lwip tcpip thread ID. */ +void sys_mark_tcpip_thread(void) +{ + lwip_tcpip_thread = osThreadGetId(); +} + +/* Check if the function was accessed with core lock or not. + Note : This function cannot be called from Interrupt Service Routines. +*/ +void sys_check_core_locking(void) +{ + osThreadId_t current_thread; + + /* Check if this function is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + LWIP_PLATFORM_ASSERT("This function cannot be called from Interrupt Service Routines"); + while(1); + } + + if (lwip_tcpip_thread != 0) + { + current_thread = osThreadGetId(); + +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("Function called without core lock", + current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0); +#else /* LWIP_TCPIP_CORE_LOCKING */ + LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + } +} +#endif /* LWIP_CHECK_MULTITHREADING */ + #endif /* !NO_SYS */ diff --git a/st_readme.txt b/st_readme.txt index 52611b2..42d5f76 100644 --- a/st_readme.txt +++ b/st_readme.txt @@ -1,52 +1,46 @@ @verbatim ****************************************************************************** - * - * Portions COPYRIGHT 2016 STMicroelectronics - * Copyright (c) 2001-2004 Swedish Institute of Computer Science, All rights reserved. - * * @file st_readme.txt - * @author MCD Application Team + * @author GPAM Application Team * @brief This file lists the main modification done by STMicroelectronics on * LwIP for integration with STM32Cube solution. * For more details on LwIP implementation on STM32Cube, please refer - * to UM1713 "Developing applications on STM32Cube with LwIP TCP/IP stack" + * to UM1713 "Developing applications on STM32Cube with LwIP TCP/IP stack" ****************************************************************************** + * @attention * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution 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 STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS 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. + * Portions Copyright (c) 2016-2025 STMicroelectronics, All rights reserved. + * Copyright (c) 2001-2004 Swedish Institute of Computer Science, All rights reserved. * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. ****************************************************************************** @endverbatim +### 04-August-2025 ### +==================== + + Upgrade to LwIP 2.2.1 + For documentation, go to https://www.nongnu.org/lwip or run Doxygen tool + (https://www.doxygen.nl/) with configuration file doc/doxygen/lwip.Doxyfile + (see doc/doxygen/generate.bat or generate.sh). + +### 06-January-2025 ### +======================== + + sys_arch.c: + - Add new LWIP_CHECK_MULTITHREADING flag to enable or disable core lock checking functions. + - Add support for recursive Mutex. + - Add new API sys_lock_tcpip_core to lock the lwip core, mark the current core lock holder and the lock count. + - Add new API sys_unlock_tcpip_core to unlock the lwip core, reset the current core lock holder and the lock count. + - Add new API sys_mark_tcpip_thread to mark the lwip tcpip thread ID. + - Add new API sys_check_core_locking to check if core locking is done correctly. + +### 02-February-2024 ### +======================== + + Upgrade to LwIP V2.2.0 version + - For more details about new features and bug fixes please refer to CHANGELOG.txt and UPGRADING files. + ### 18-August-2023 ### ======================== + Add LICENSE.md file at the root directory.