diff --git a/.gitignore b/.gitignore index 0f13a3e8..0092ea6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/doc/doxygen/output +/doc/doxygen/output/html /src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/ /src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/ /src/apps/snmp/LwipMibCompiler/LwipMibCompiler/bin/ diff --git a/CHANGELOG b/CHANGELOG index 39177b8f..8f030fde 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -328,6 +328,10 @@ HISTORY ++ Bugfixes: + 2016-08-23: Simon Goldschmidt + * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need + it any more after implementing unicast ARP renewal towards arp entry timeout + 2016-07-20: Simon Goldschmidt * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC) diff --git a/FILES b/FILES index 66253196..e6e09989 100644 --- a/FILES +++ b/FILES @@ -1,4 +1,5 @@ src/ - The source code for the lwIP TCP/IP stack. doc/ - The documentation for lwIP. +test/ - Some code to test whether the sources do what they should. See also the FILES file in each subdirectory. diff --git a/README b/README index fb881317..0884d27b 100644 --- a/README +++ b/README @@ -35,6 +35,9 @@ APPLICATIONS * HTTP server with SSI and CGI * SNMPv2c agent with MIB compiler (Simple Network Management Protocol) * SNTP (Simple network time protocol) + * NetBIOS name service responder + * MDNS (Multicast DNS) responder + * iPerf server implementation LICENSE @@ -77,7 +80,7 @@ Self documentation of the source code is regularly extracted from the current Git sources and is available from this web page: http://www.nongnu.org/lwip/ -There is now a constantly growin wiki about lwIP at +There is now a constantly growing wiki about lwIP at http://lwip.wikia.com/wiki/LwIP_Wiki Also, there are mailing lists you can subscribe at diff --git a/UPGRADING b/UPGRADING index f44fb487..c42c67d1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -20,7 +20,7 @@ with newer versions. * Added IPv6 support (dual-stack or IPv4/IPv6 only) * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); - supports SNMP2vc (experimental v3 support) + supports SNMPv2c (experimental v3 support) * Moved some core applications from contrib repository to src/apps (and include/lwip/apps) +++ Raw API: @@ -34,7 +34,8 @@ with newer versions. ++ Port changes +++ new files: - * MANY new and moved files! + * MANY new and moved files! + * Added src/Filelists.mk for use in Makefile projects * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" to let abc.h only contain the actual application programmer's API @@ -45,6 +46,13 @@ with newer versions. * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread instead of using one per netconn (these semaphores are used even with core locking enabled as some longer lasting functions like big writes still need to delay) + * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() + in def.h (to be overridden in cc.h) instead of config + options for netbiosns, httpd, dns, etc. ... + * New abstraction for hton* and ntoh* functions in def.h. + To override them, use the following in cc.h: + #define lwip_htons(x) + #define lwip_htonl(x) +++ new options: * TODO @@ -56,6 +64,8 @@ with newer versions. * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item is now available + * Signature of LWIP_HOOK_VLAN_SET macro was changed + * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) or to move buffers to dedicated memory using compiler attributes @@ -68,6 +78,7 @@ with newer versions. * Added IPv6 support (dual-stack or IPv4/IPv6 only) * Major rewrite of PPP (incl. keep-up with apache pppd) + see doc/ppp.txt for an upgrading how-to * Major rewrite of SNMP (incl. MIB parser) * Fixed timing issues that might have lead to losing a DHCP lease * Made rx processing path more robust against crafted errors @@ -77,7 +88,7 @@ with newer versions. * support PBUF_REF for RX packets * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate threads each (needs LWIP_NETCONN_SEM_PER_THREAD) - * Moved and reorderd stats (mainly memp/mib2) + * Moved and reordered stats (mainly memp/mib2) (1.4.0) diff --git a/doc/FILES b/doc/FILES index 05d356f4..e5885750 100644 --- a/doc/FILES +++ b/doc/FILES @@ -1,6 +1,9 @@ +doxygen/ - Configuration files and scripts to create the lwIP doxygen source + documentation (found at http://www.nongnu.org/lwip/) + savannah.txt - How to obtain the current development source code. contrib.txt - How to contribute to lwIP as a developer. rawapi.txt - The documentation for the core API of lwIP. Also provides an overview about the other APIs and multithreading. -snmp_agent.txt - The documentation for the lwIP SNMP agent. sys_arch.txt - The documentation for a system abstraction layer of lwIP. +ppp.txt - Documentation of the PPP interface for lwIP. diff --git a/doc/NO_SYS_SampleCode.c b/doc/NO_SYS_SampleCode.c new file mode 100644 index 00000000..f5c6c10b --- /dev/null +++ b/doc/NO_SYS_SampleCode.c @@ -0,0 +1,117 @@ +void eth_mac_irq() +{ + /* Service MAC IRQ here */ + + /* Allocate pbuf from pool (avoid using heap in interrupts) */ + struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL); + + if(p != NULL) { + /* Copy ethernet frame into pbuf */ + pbuf_take(p, eth_data, eth_data_count); + + /* Put in a queue which is processed in main loop */ + if(!queue_try_put(&queue, p)) { + /* queue is full -> packet loss */ + pbuf_free(p); + } + } +} + +static err_t netif_output(struct netif *netif, struct pbuf *p) +{ + LINK_STATS_INC(link.xmit); + + /* Update SNMP stats (only if you use SNMP) */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); + int unicast = ((p->payload[0] & 0x01) == 0); + if (unicast) { + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } else { + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } + + lock_interrupts(); + pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0); + /* Start MAC transmit here */ + unlock_interrupts(); + + return ERR_OK; +} + +static void netif_status_callback(struct netif *netif) +{ + printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); +} + +static err_t netif_init(struct netif *netif) +{ + netif->linkoutput = netif_output; + netif->output = etharp_output; + netif->output_ip6 = ethip6_output; + netif->mtu = ETHERNET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000); + + SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr)); + netif->hwaddr_len = sizeof(netif->hwaddr); + + return ERR_OK; +} + +void main(void) +{ + struct netif netif; + + lwip_init(); + + netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input); + netif.name[0] = 'e'; + netif.name[1] = '0'; + netif_create_ip6_linklocal_address(&netif, 1); + netif.ip6_autoconfig_enabled = 1; + netif_set_status_callback(&netif, netif_status_callback); + netif_set_default(&netif); + netif_set_up(&netif); + + /* Start DHCP and HTTPD */ + dhcp_init(); + httpd_init(); + + while(1) { + /* Check link state, e.g. via MDIO communication with PHY */ + if(link_state_changed()) { + if(link_is_up()) { + netif_set_link_up(&netif); + } else { + netif_set_link_down(&netif); + } + } + + /* Check for received frames, feed them to lwIP */ + lock_interrupts(); + struct pbuf* p = queue_try_get(&queue); + unlock_interrupts(); + + if(p != NULL) { + LINK_STATS_INC(link.recv); + + /* Update SNMP stats (only if you use SNMP) */ + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + int unicast = ((p->payload[0] & 0x01) == 0); + if (unicast) { + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } else { + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } + + if(netif.input(p, &netif) != ERR_OK) { + pbuf_free(p); + } + } + + /* Cyclic lwIP timers check */ + sys_check_timeouts(); + + /* your application goes here */ + } +} diff --git a/doc/contrib.txt b/doc/contrib.txt index fa11dfec..6f0d7bc5 100644 --- a/doc/contrib.txt +++ b/doc/contrib.txt @@ -39,7 +39,7 @@ features of Savannah help us not lose users' input. bugtracker at Savannah. 3. If you have a fix put the patch on Savannah. If it is a patch that affects both core and arch specific stuff please separate them so that the core can - be applied separately while leaving the other patch 'open'. The prefered way + be applied separately while leaving the other patch 'open'. The preferred way is to NOT touch archs you can't test and let maintainers take care of them. This is a good way to see if they are used at all - the same goes for unix netifs except tapif. diff --git a/doc/doxygen/lwip.Doxyfile b/doc/doxygen/lwip.Doxyfile index f9d5fc17..125d3239 100644 --- a/doc/doxygen/lwip.Doxyfile +++ b/doc/doxygen/lwip.Doxyfile @@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = ../../ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -781,7 +781,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../../src main_page.h +INPUT = main_page.h ../../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -2071,6 +2071,7 @@ INCLUDE_FILE_PATTERNS = *.h PREDEFINED = __DOXYGEN__=1 \ NO_SYS=0 \ SYS_LIGHTWEIGHT_PROT=1 \ + LWIP_TCPIP_CORE_LOCKING=1 \ LWIP_IPV4=1 \ LWIP_IPV6=1 \ LWIP_ICMP=1 \ @@ -2080,10 +2081,12 @@ PREDEFINED = __DOXYGEN__=1 \ LWIP_UDP=1 \ LWIP_IGMP=1 \ LWIP_TCP=1 \ + TCP_LISTEN_BACKLOG=1 \ LWIP_SNMP=1 \ SNMP_USE_NETCONN=1 \ SNMP_USE_RAW=1 \ MIB2_STATS=1 \ + LWIP_MDNS_RESPONDER=1 \ MEMP_OVERFLOW_CHECK=0 \ MEMP_SANITY_CHECK=1 \ LWIP_ARP=1 \ @@ -2091,8 +2094,10 @@ PREDEFINED = __DOXYGEN__=1 \ LWIP_NETIF_HOSTNAME=1 \ LWIP_NETIF_API=1 \ LWIP_NETIF_CALLBACK=1 \ + LWIP_NETIF_STATUS_CALLBACK=1 \ LWIP_NETIF_REMOVE_CALLBACK=1 \ LWIP_NETIF_LINK_CALLBACK=1 \ + LWIP_NUM_NETIF_CLIENT_DATA=1 \ ENABLE_LOOPBACK=1 \ LWIP_AUTOIP=1 \ ARP_QUEUEING=1 \ @@ -2110,10 +2115,8 @@ PREDEFINED = __DOXYGEN__=1 \ SO_REUSE=1 \ SO_REUSE_RXTOALL=1 \ LWIP_HAVE_SLIPIF=1 \ - LWIP_6LOWPAN=1 \ - "LWIP_DNS && LWIP_SOCKET " \ - "(LWIP_DNS && LWIP_SOCKET)=1 " - + LWIP_6LOWPAN=1 + # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The # macro definition that is found in the sources will be used. Use the PREDEFINED diff --git a/doc/doxygen/main_page.h b/doc/doxygen/main_page.h index 9f01d9f3..31cc0df6 100644 --- a/doc/doxygen/main_page.h +++ b/doc/doxygen/main_page.h @@ -1,4 +1,4 @@ -/** +/** * @defgroup lwip lwIP * * @defgroup infrastructure Infrastructure @@ -7,8 +7,8 @@ * Non thread-safe APIs, callback style for maximum performance and minimum * memory footprint. * - * @defgroup threadsafe_api Thread-safe APIs - * Thread-safe APIs, blocking functions. More overhead, but can be called + * @defgroup sequential_api Sequential-style APIs + * Sequential-style APIs, blocking functions. More overhead, but can be called * from any thread except TCPIP thread. * * @defgroup addons Addons @@ -30,3 +30,97 @@ * @page contrib How to contribute to lwIP * @verbinclude "contrib.txt" */ + +/** + * @page pitfalls Common pitfalls + * + * Multiple Execution Contexts in lwIP code + * ======================================== + * + * The most common source of lwIP problems is to have multiple execution contexts + * inside the lwIP code. + * + * lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS + * running on target system) or @ref lwip_os (there is an OS running + * on the target system). + * + * Mainloop Mode + * ------------- + * In mainloop mode, only @ref callbackstyle_api can be used. + * The user has two possibilities to ensure there is only one + * exection context at a time in lwIP: + * + * 1) Deliver RX ethernet packets directly in interrupt context to lwIP + * by calling netif->input directly in interrupt. This implies all lwIP + * callback functions are called in IRQ context, which may cause further + * problems in application code: IRQ is blocked for a long time, multiple + * execution contexts in application code etc. When the application wants + * to call lwIP, it only needs to disable interrupts during the call. + * If timers are involved, even more locking code is needed to lock out + * timer IRQ and ethernet IRQ from each other, assuming these may be nested. + * + * 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys. + * lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ + * has to put received telegrams into a queue which is polled in the + * mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g. + * some SPI IRQ wants to forward data to udp_send() or tcp_write()! + * + * OS Mode + * ------- + * In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used. + * @ref sequential_api are designed to be called from threads other than + * the TCPIP thread, so there is nothing to consider here. + * But @ref callbackstyle_api functions must _ONLY_ be called from + * TCPIP thread. It is a common error to call these from other threads + * or from IRQ contexts. ​Ethernet RX needs to deliver incoming packets + * in the correct way by sending a message to TCPIP thread, this is + * implemented in tcpip_input().​​ + * Again, ensure lwIP is _NEVER_ called from an interrupt, e.g. + * some SPI IRQ wants to forward data to udp_send() or tcp_write()! + * + * 1) tcpip_callback() can be used get called back from TCPIP thread, + * it is safe to call any @ref callbackstyle_api from there. + * + * 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api + * functions can be called when lwIP core lock is aquired, see + * @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE(). + * These macros cannot be used in an interrupt context! + * Note the OS must correctly handle priority inversion for this. + */ + +/** + * @page bugs Reporting bugs + * Please report bugs in the lwIP bug tracker at savannah.\n + * BEFORE submitting, please check if the bug has already been reported!\n + * https://savannah.nongnu.org/bugs/?group=lwip + */ + +/** + * @defgroup lwip_nosys Mainloop mode ("NO_SYS") + * @ingroup lwip + * Use this mode if you do not run an OS on your system. \#define NO_SYS to 1. + * Feed incoming packets to netif->input(pbuf, netif) function from mainloop, + * *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt + * context and put them into a queue which is processed from mainloop.\n + * Call sys_check_timeouts() periodically in the mainloop.\n + * Porting: implement all functions in @ref sys_time and @ref sys_prot.\n + * You can only use @ref callbackstyle_api in this mode.\n + * Sample code:\n + * @include NO_SYS_SampleCode.c + */ + +/** + * @defgroup lwip_os OS mode (TCPIP thread) + * @ingroup lwip + * Use this mode if you run an OS on your system. It is recommended to + * use an RTOS that correctly handles priority inversion and + * to use @ref LWIP_TCPIP_CORE_LOCKING.\n + * Porting: implement all functions in @ref sys_layer.\n + * You can use @ref callbackstyle_api together with @ref tcpip_callback, + * and all @ref sequential_api. + */ + +/** + * @page raw_api lwIP API + * @verbinclude "rawapi.txt" + */ diff --git a/doc/doxygen/output/index.html b/doc/doxygen/output/index.html new file mode 100644 index 00000000..a52e09fc --- /dev/null +++ b/doc/doxygen/output/index.html @@ -0,0 +1,10 @@ + + + + Redirection + + + + index.html + + diff --git a/doc/mdns.txt b/doc/mdns.txt new file mode 100644 index 00000000..c3228432 --- /dev/null +++ b/doc/mdns.txt @@ -0,0 +1,113 @@ +Multicast DNS for lwIP + +Author: Erik Ekman + + +Note! The MDNS responder does not have all features required by the standards. +See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal +cases - but watch out if many devices on the same network try to use the same +host/service instance names. + + +How to enable: +============== + +MDNS support does not depend on DNS. +MDNS supports using IPv4 only, v6 only, or v4+v6. + +To enable MDNS responder, set + LWIP_MDNS_RESPONDER = 1 +in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build. + +The max number of services supported per netif is defined by MDNS_MAX_SERVICES, +default is 1. + +Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB. +Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif). + +MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1. +MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is +generated. + +The MDNS code puts its structs on the stack where suitable to reduce dynamic +memory allocation. It may use up to 1kB of stack. + +MDNS needs a strncasecmp() implementation. If you have one, define +LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation +for you. + + +How to use: +=========== + +Call mdns_resp_init() during system initialization. +This opens UDP sockets on port 5353 for IPv4 and IPv6. + + +To start responding on a netif, run + mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl) + +The hostname will be copied. If this returns successfully, the netif will join +the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast +to port 5353 will be handled: +- .local type A, AAAA or ANY returns relevant IP addresses +- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses + returns .local +Answers will use the supplied TTL (in seconds) +MDNS allows UTF-8 names, but it is recommended to stay within ASCII, +since the default case-insensitive comparison assumes this. + +It is recommended to call this function after an IPv4 address has been set, +since there is currently no check if the v4 address is valid. + +Call mdns_resp_netif_settings_changed() every time the IP address +on the netif has changed. + +To stop responding on a netif, run + mdns_resp_remove_netif(struct netif *netif) + + +Adding services: +================ + +The netif first needs to be registered. Then run + mdns_resp_add_service(struct netif *netif, char *name, char *service, + u16_t proto, u16_t port, u32_t dns_ttl, + service_get_txt_fn_t txt_fn, void *txt_userdata); + +The name and service pointers will be copied. Name refers to the name of the +service instance, and service is the type of service, like _http +proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp. +If this call returns successfully, the following queries will be answered: +- _services._dns-sd._udp.local type PTR returns ..local +- ..local type PTR returns ...local +- ...local type SRV returns hostname and port of service +- ...local type TXT builds text strings by calling txt_fn + with the supplied userdata. The callback adds strings to the reply by calling + mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, + int txt_len). Example callback method: + + static void srv_txt(struct mdns_service *service, void *txt_userdata) + { + res = mdns_resp_add_service_txtitem(service, "path=/", 6); + LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); + } + + Since a hostname struct is used for TXT storage each single item can be max + 63 bytes long, and the total max length (including length bytes for each + item) is 255 bytes. + +If your device runs a webserver on port 80, an example call might be: + + mdns_resp_add_service(netif, "myweb", "_http" + DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); + +which will publish myweb._http._tcp.local for any hosts looking for web servers, +and point them to .local:80 + +Relevant information will be sent as additional records to reduce number of +requests required from a client. + +Removing services is currently not supported. Services are removed when the +netif is removed. + diff --git a/doc/ppp.txt b/doc/ppp.txt index e40c0126..8b88b3a6 100644 --- a/doc/ppp.txt +++ b/doc/ppp.txt @@ -79,7 +79,7 @@ static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { switch(err_code) { case PPPERR_NONE: { #if LWIP_DNS - ip_addr_t ns; + const ip_addr_t *ns; #endif /* LWIP_DNS */ printf("status_cb: Connected\n"); #if PPP_IPV4_SUPPORT @@ -88,9 +88,9 @@ static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); #if LWIP_DNS ns = dns_getserver(0); - printf(" dns1 = %s\n", ipaddr_ntoa(&ns)); + printf(" dns1 = %s\n", ipaddr_ntoa(ns)); ns = dns_getserver(1); - printf(" dns2 = %s\n", ipaddr_ntoa(&ns)); + printf(" dns2 = %s\n", ipaddr_ntoa(ns)); #endif /* LWIP_DNS */ #endif /* PPP_IPV4_SUPPORT */ #if PPP_IPV6_SUPPORT diff --git a/doc/rawapi.txt b/doc/rawapi.txt index ce5b42ab..0cdfdcea 100644 --- a/doc/rawapi.txt +++ b/doc/rawapi.txt @@ -171,15 +171,6 @@ incoming connections or be explicitly connected to another host. in the listen queue to the value specified by the backlog argument. To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. -- void tcp_accepted(struct tcp_pcb *pcb) - - Inform lwIP that an incoming connection has been accepted. This would - usually be called from the accept callback. This allows lwIP to perform - housekeeping tasks, such as allowing further incoming connections to be - queued in the listen backlog. - ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed - into the accept callback! - - void tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) @@ -465,9 +456,11 @@ introduction to this subject. Other significant improvements can be made by supplying assembly or inline replacements for htons() and htonl() if you're using a little-endian architecture. -#define LWIP_PLATFORM_BYTESWAP 1 -#define LWIP_PLATFORM_HTONS(x) -#define LWIP_PLATFORM_HTONL(x) +#define lwip_htons(x) +#define lwip_htonl(x) +If you #define them to htons() and htonl(), you should +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from +defining hton*/ntoh* compatibility macros. Check your network interface driver if it reads at a higher speed than the maximum wire-speed. If the diff --git a/doc/sys_arch.txt b/doc/sys_arch.txt index 847cd777..333946da 100644 --- a/doc/sys_arch.txt +++ b/doc/sys_arch.txt @@ -1,6 +1,7 @@ -sys_arch interface for lwIP 0.6++ +sys_arch interface for lwIP Author: Adam Dunkels + Simon Goldschmidt The operating system emulation layer provides a common interface between the lwIP code and the underlying operating system kernel. The @@ -9,12 +10,11 @@ small changes to a few header files and a new sys_arch implementation. It is also possible to do a sys_arch implementation that does not rely on any underlying operating system. -The sys_arch provides semaphores and mailboxes to lwIP. For the full +The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full lwIP functionality, multiple threads support can be implemented in the sys_arch, but this is not required for the basic lwIP -functionality. Previous versions of lwIP required the sys_arch to -implement timer scheduling as well but as of lwIP 0.5 this is -implemented in a higher layer. +functionality. Timer scheduling is implemented in lwIP, but can be implemented +by the sys_arch port (LWIP_TIMERS_CUSTOM==1). In addition to the source file providing the functionality of sys_arch, the OS emulation layer must provide several header files defining @@ -22,19 +22,18 @@ macros used throughout lwip. The files required and the macros they must define are listed below the sys_arch description. Semaphores can be either counting or binary - lwIP works with both -kinds. Mailboxes are used for message passing and can be implemented -either as a queue which allows multiple messages to be posted to a -mailbox, or as a rendez-vous point where only one message can be -posted at a time. lwIP works with both kinds, but the former type will -be more efficient. A message in a mailbox is just a pointer, nothing -more. +kinds. Mailboxes should be implemented as a queue which allows multiple messages +to be posted (implementing as a rendez-vous point where only one message can be +posted at a time can have a highly negative impact on performance). A message +in a mailbox is just a pointer, nothing more. Semaphores are represented by the type "sys_sem_t" which is typedef'd in the sys_arch.h file. Mailboxes are equivalently represented by the -type "sys_mbox_t". lwIP does not place any restrictions on how -sys_sem_t or sys_mbox_t are represented internally. +type "sys_mbox_t". Mutexes are represented ny the type "sys_mutex_t". +lwIP does not place any restrictions on how these types are represented +internally. -Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that +Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that allows both using pointers or actual OS structures to be used. This way, memory required for such types can be either allocated in place (globally or on the stack) or on the heap (allocated internally in the "*_new()" functions). @@ -94,6 +93,40 @@ The following functions must be implemented by the sys_arch: sys_sem_free() is always called before calling this function! This may also be a define, in which case the function is not prototyped. +- void sys_mutex_new(sys_mutex_t *mutex) + + Creates a new mutex. The mutex is allocated to the memory that 'mutex' + points to (which can be both a pointer or the actual OS structure). + If the mutex has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mutex_free(sys_mutex_t *mutex) + + Deallocates a mutex. + +- void sys_mutex_lock(sys_mutex_t *mutex) + + Blocks the thread until the mutex can be grabbed. + +- void sys_mutex_unlock(sys_mutex_t *mutex) + + Releases the mutex previously locked through 'sys_mutex_lock()'. + +- void sys_mutex_valid(sys_mutex_t *mutex) + + Returns 1 if the mutes is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mutex_set_invalid(sys_mutex_t *mutex) + + Invalidate a mutex so that sys_mutex_valid() returns 0. + ATTENTION: This does NOT mean that the mutex shall be deallocated: + sys_mutex_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + - err_t sys_mbox_new(sys_mbox_t *mbox, int size) Creates an empty mailbox for maximum "size" elements. Elements stored @@ -176,6 +209,9 @@ to be implemented as well: the "stacksize" parameter. The id of the new thread is returned. Both the id and the priority are system dependent. +When lwIP is used from more than one context (e.g. from multiple threads OR from +main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled! + - sys_prot_t sys_arch_protect(void) This optional function does a "fast" critical region protection and returns @@ -209,7 +245,7 @@ For some configurations, you also need: Note: -Be carefull with using mem_malloc() in sys_arch. When malloc() refers to +Be careful with using mem_malloc() in sys_arch. When malloc() refers to mem_malloc() you can run into a circular function call problem. In mem.c mem_init() tries to allcate a semaphore using mem_malloc, which of course can't be performed when sys_arch uses mem_malloc. diff --git a/src/FILES b/src/FILES index 952aeabb..0be0741d 100644 --- a/src/FILES +++ b/src/FILES @@ -1,13 +1,15 @@ api/ - The code for the high-level wrapper API. Not needed if you use the lowel-level call-back/raw API. +apps/ - Higher layer applications that are specifically programmed + with the lwIP low-level raw API. + core/ - The core of the TPC/IP stack; protocol implementations, memory and buffer management, and the low-level raw API. include/ - lwIP include files. -netif/ - Generic network interface device drivers are kept here, - as well as the ARP module. +netif/ - Generic network interface device drivers are kept here. For more information on the various subdirectories, check the FILES file in each directory. diff --git a/src/Filelists.mk b/src/Filelists.mk index b3b14ebf..ac79422c 100644 --- a/src/Filelists.mk +++ b/src/Filelists.mk @@ -158,12 +158,20 @@ LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c # SNTPFILES: SNTP client SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c +# MDNSFILES: MDNS responder +MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c + # NETBIOSNSFILES: NetBIOS name server NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c +# TFTPFILES: TFTP server files +TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c + # LWIPAPPFILES: All LWIP APPs LWIPAPPFILES=$(SNMPFILES) \ $(HTTPDFILES) \ $(LWIPERFFILES) \ $(SNTPFILES) \ - $(NETBIOSNSFILES) + $(MDNSFILES) \ + $(NETBIOSNSFILES) \ + $(TFTPFILES) diff --git a/src/api/api_lib.c b/src/api/api_lib.c index 5e696d88..b4fc403d 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -1,6 +1,24 @@ /** * @file * Sequential API External module + * + * @defgroup netconn Netconn API + * @ingroup sequential_api + * Thread-safe, to be called from non-TCPIP threads only. + * TX/RX handling based on @ref netbuf (containing @ref pbuf) + * to avoid copying data around. + * + * @defgroup netconn_common Common functions + * @ingroup netconn + * For use with TCP and UDP + * + * @defgroup netconn_tcp TCP only + * @ingroup netconn + * TCP only functions + * + * @defgroup netconn_udp UDP only + * @ingroup netconn + * UDP only functions */ /* @@ -34,26 +52,6 @@ * Author: Adam Dunkels */ -/** - * @defgroup netconn Netconn API - * @ingroup threadsafe_api - * Thread-safe, to be called from non-TCPIP threads only. - * TX/RX handling based on @ref netbuf (containing @ref pbuf) - * to avoid copying data around. - * - * @defgroup netconn_common Common functions - * @ingroup netconn - * For use with TCP and UDP - * - * @defgroup netconn_tcp TCP only - * @ingroup netconn - * TCP only functions - * - * @defgroup netconn_udp UDP only - * @ingroup netconn - * UDP only functions - */ - /* This is the part of the API that is linked with the application */ @@ -243,8 +241,8 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) * Binding one netconn twice might not always be checked correctly! * * @param conn the netconn to bind - * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY - * to bind to all addresses) + * @param addr the local IP address to bind the netconn to + * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) * @param port the local port to bind the netconn to (not used for RAW) * @return ERR_OK if bound, any other err_t on failure */ @@ -258,7 +256,7 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ if (addr == NULL) { - addr = IP_ADDR_ANY; + addr = IP4_ADDR_ANY; } API_MSG_VAR_ALLOC(msg); @@ -290,7 +288,7 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ if (addr == NULL) { - addr = IP_ADDR_ANY; + addr = IP4_ADDR_ANY; } API_MSG_VAR_ALLOC(msg); @@ -308,7 +306,7 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) * Disconnect a netconn from its current peer (only valid for UDP netconns). * * @param conn the netconn to disconnect - * @return @todo: return value is not set here... + * @return See @ref err_t */ err_t netconn_disconnect(struct netconn *conn) @@ -546,6 +544,10 @@ netconn_recv_data(struct netconn *conn, void **new_buf) /* If we are closed, we indicate that we no longer wish to use the socket */ if (buf == NULL) { API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + if (conn->pcb.ip == NULL) { + /* race condition: RST during recv */ + return conn->last_err == ERR_OK ? ERR_RST : conn->last_err; + } /* RX side is closed, so deallocate the recvmbox */ netconn_close_shutdown(conn, NETCONN_SHUT_RD); /* Don' store ERR_CLSD as conn->err since we are only half-closed */ @@ -869,10 +871,10 @@ netconn_join_leave_group(struct netconn *conn, /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ if (multiaddr == NULL) { - multiaddr = IP_ADDR_ANY; + multiaddr = IP4_ADDR_ANY; } if (netif_addr == NULL) { - netif_addr = IP_ADDR_ANY; + netif_addr = IP4_ADDR_ANY; } API_MSG_VAR_REF(msg).conn = conn; diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 9dfea64e..86546c29 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -540,7 +540,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) * Called from lwip_netconn_do_newconn(). * * @param msg the api_msg_msg describing the connection type - * @return msg->conn->err, but the return value is currently ignored */ static void pcb_new(struct api_msg *msg) @@ -781,16 +780,18 @@ netconn_drain(struct netconn *conn) #if LWIP_TCP if (sys_mbox_valid(&conn->acceptmbox)) { while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { - struct netconn *newconn = (struct netconn *)mem; - /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ - /* pcb might be set to NULL already by err_tcp() */ - /* drain recvmbox */ - netconn_drain(newconn); - if (newconn->pcb.tcp != NULL) { - tcp_abort(newconn->pcb.tcp); - newconn->pcb.tcp = NULL; + if (mem != &netconn_aborted) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); } - netconn_free(newconn); } sys_mbox_free(&conn->acceptmbox); sys_mbox_set_invalid(&conn->acceptmbox); @@ -805,7 +806,6 @@ netconn_drain(struct netconn *conn) * places. * * @param conn the TCP netconn to close - * [@param delay 1 if called from sent/poll (wake up calling thread on end)] */ static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) @@ -1490,7 +1490,6 @@ lwip_netconn_do_accepted(void *m) * blocking application thread (waiting in netconn_write) is released. * * @param conn netconn (that is currently in state NETCONN_WRITE) to process - * [@param delay 1 if called from sent/poll (wake up calling thread on end)] * @return ERR_OK * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished */ @@ -1512,9 +1511,8 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", conn->write_offset < conn->current_msg->msg.w.len); - dontblock = netconn_is_nonblocking(conn) || - (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); apiflags = conn->current_msg->msg.w.apiflags; + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); #if LWIP_SO_SNDTIMEO if ((conn->send_timeout != 0) && @@ -1604,7 +1602,6 @@ err_mem: err = out_err; write_finished = 1; conn->current_msg->msg.w.len = 0; - } else { } } else { /* On errors != ERR_MEM, we don't try writing any more but return diff --git a/src/api/err.c b/src/api/err.c index f3650f4c..1593e70a 100644 --- a/src/api/err.c +++ b/src/api/err.c @@ -37,6 +37,34 @@ */ #include "lwip/err.h" +#include "lwip/def.h" +#include "lwip/sys.h" + +#include "lwip/errno.h" + +#if !NO_SYS +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ALREADY -9 Already connecting. */ + EISCONN, /* ERR_ISCONN -10 Conn already established.*/ + ENOTCONN, /* ERR_CONN -11 Not connected. */ + -1, /* ERR_IF -12 Low-level netif error */ + ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ + ECONNRESET, /* ERR_RST -14 Connection reset. */ + ENOTCONN, /* ERR_CLSD -15 Connection closed. */ + EIO /* ERR_ARG -16 Illegal argument. */ +}; +#endif /* !NO_SYS */ #ifdef LWIP_DEBUG @@ -69,7 +97,21 @@ static const char *err_strerr[] = { const char * lwip_strerr(err_t err) { + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) { + return "Unknown error."; + } return err_strerr[-err]; } #endif /* LWIP_DEBUG */ + +#if !NO_SYS +int +err_to_errno(err_t err) +{ + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) { + return EIO; + } + return err_to_errno_table[-err]; +} +#endif /* !NO_SYS */ diff --git a/src/api/netbuf.c b/src/api/netbuf.c index 342717be..eb250115 100644 --- a/src/api/netbuf.c +++ b/src/api/netbuf.c @@ -2,6 +2,12 @@ * @file * Network buffer management * + * @defgroup netbuf Network buffers + * @ingroup netconn + * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally + * to avoid copying data around.\n + * Buffers must not be shared accross multiple threads, all functions except + * netbuf_new() and netbuf_delete() are not thread-safe. */ /* @@ -36,15 +42,6 @@ * */ -/** - * @defgroup netbuf Network buffers - * @ingroup netconn - * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally - * to avoid copying data around.\n - * Buffers must not be shared accross multiple threads, all functions except - * netbuf_new() and netbuf_delete() are not thread-safe. - */ - #include "lwip/opt.h" #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ @@ -69,23 +66,9 @@ netbuf *netbuf_new(void) buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); if (buf != NULL) { - buf->p = NULL; - buf->ptr = NULL; - ip_addr_set_zero(&buf->addr); - buf->port = 0; -#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -#if LWIP_CHECKSUM_ON_COPY - buf->flags = 0; -#endif /* LWIP_CHECKSUM_ON_COPY */ - buf->toport_chksum = 0; -#if LWIP_NETBUF_RECVINFO - ip_addr_set_zero(&buf->toaddr); -#endif /* LWIP_NETBUF_RECVINFO */ -#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ - return buf; - } else { - return NULL; + memset(buf, 0, sizeof(struct netbuf)); } + return buf; } /** @@ -188,7 +171,7 @@ netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) void netbuf_chain(struct netbuf *head, struct netbuf *tail) { - LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); pbuf_cat(head->p, tail->p); head->ptr = head->p; @@ -234,7 +217,7 @@ netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) s8_t netbuf_next(struct netbuf *buf) { - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); if (buf->ptr->next == NULL) { return -1; } @@ -256,7 +239,7 @@ netbuf_next(struct netbuf *buf) void netbuf_first(struct netbuf *buf) { - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); buf->ptr = buf->p; } diff --git a/src/api/netdb.c b/src/api/netdb.c index f9d63d46..ef0c79b1 100644 --- a/src/api/netdb.c +++ b/src/api/netdb.c @@ -2,6 +2,8 @@ * @file * API functions for name resolving * + * @defgroup netdbapi NETDB API + * @ingroup socket */ /* @@ -33,12 +35,6 @@ * */ - -/** - * @defgroup netdbapi NETDB API - * @ingroup socket - */ - #include "lwip/netdb.h" #if LWIP_DNS && LWIP_SOCKET @@ -379,7 +375,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname, inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); - sa6->sin6_port = htons((u16_t)port_nr); + sa6->sin6_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET6; #endif /* LWIP_IPV6 */ } else { @@ -389,7 +385,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname, inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = htons((u16_t)port_nr); + sa4->sin_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET; #endif /* LWIP_IPV4 */ } diff --git a/src/api/netifapi.c b/src/api/netifapi.c index 3a02d521..fef05a34 100644 --- a/src/api/netifapi.c +++ b/src/api/netifapi.c @@ -2,6 +2,13 @@ * @file * Network Interface Sequential API module * + * @defgroup netifapi NETIF API + * @ingroup sequential_api + * Thread-safe functions to be called from non-TCPIP threads + * + * @defgroup netifapi_netif NETIF related + * @ingroup netifapi + * To be called from non-TCPIP threads */ /* @@ -31,16 +38,6 @@ * */ -/** - * @defgroup netifapi NETIF API - * @ingroup threadsafe_api - * Thread-safe functions to be called from non-TCPIP threads - * - * @defgroup netifapi_netif NETIF related - * @ingroup netifapi - * To be called from non-TCPIP threads - */ - #include "lwip/opt.h" #if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ @@ -137,13 +134,13 @@ netifapi_netif_add(struct netif *netif, #if LWIP_IPV4 if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; + ipaddr = IP4_ADDR_ANY4; } if (netmask == NULL) { - netmask = IP4_ADDR_ANY; + netmask = IP4_ADDR_ANY4; } if (gw == NULL) { - gw = IP4_ADDR_ANY; + gw = IP4_ADDR_ANY4; } #endif /* LWIP_IPV4 */ @@ -180,13 +177,13 @@ netifapi_netif_set_addr(struct netif *netif, NETIFAPI_VAR_ALLOC(msg); if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; + ipaddr = IP4_ADDR_ANY4; } if (netmask == NULL) { - netmask = IP4_ADDR_ANY; + netmask = IP4_ADDR_ANY4; } if (gw == NULL) { - gw = IP4_ADDR_ANY; + gw = IP4_ADDR_ANY4; } NETIFAPI_VAR_REF(msg).netif = netif; diff --git a/src/api/sockets.c b/src/api/sockets.c index 6547182c..9968a9ae 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -2,6 +2,12 @@ * @file * Sockets BSD-Like API module * + * @defgroup socket Socket API + * @ingroup sequential_api + * BSD-style socket API.\n + * Thread-safe, to be called from non-TCPIP threads only.\n + * Can be activated by defining @ref LWIP_SOCKET to 1.\n + * Header is in posix/sys/socket.h\b */ /* @@ -38,15 +44,6 @@ * */ -/** - * @defgroup socket Socket API - * @ingroup threadsafe_api - * BSD-style socket API.\n - * Thread-safe, to be called from non-TCPIP threads only.\n - * Can be activated by defining LWIP_SOCKET to 1.\n - * Header is in posix/sys/socket.h\b - */ - #include "lwip/opt.h" #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ @@ -84,25 +81,25 @@ #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ (sin)->sin_len = sizeof(struct sockaddr_in); \ (sin)->sin_family = AF_INET; \ - (sin)->sin_port = htons((port)); \ + (sin)->sin_port = lwip_htons((port)); \ inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \ memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ - (port) = ntohs((sin)->sin_port); }while(0) + (port) = lwip_ntohs((sin)->sin_port); }while(0) #endif /* LWIP_IPV4 */ #if LWIP_IPV6 #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = htons((port)); \ + (sin6)->sin6_port = lwip_htons((port)); \ (sin6)->sin6_flowinfo = 0; \ inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ (sin6)->sin6_scope_id = 0; }while(0) #define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ - (port) = ntohs((sin6)->sin6_port); }while(0) + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) #endif /* LWIP_IPV6 */ #if LWIP_IPV4 && LWIP_IPV6 @@ -269,8 +266,8 @@ union sockaddr_aligned { /* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when a socket is closed */ struct lwip_socket_multicast_pair { - /** the socket (+1 to not require initialization) */ - int sa; + /** the socket */ + struct lwip_sock* sock; /** the interface address */ ip4_addr_t if_addr; /** the group address */ @@ -292,34 +289,6 @@ static struct lwip_select_cb *select_cb_list; and checked in event_callback to see if it has changed. */ static volatile int select_cb_ctr; -/** Table to quickly map an lwIP error (err_t) to a socket error - * by using -err as an index */ -static const int err_to_errno_table[] = { - 0, /* ERR_OK 0 No error, everything OK. */ - ENOMEM, /* ERR_MEM -1 Out of memory error. */ - ENOBUFS, /* ERR_BUF -2 Buffer error. */ - EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ - EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ - EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ - EINVAL, /* ERR_VAL -6 Illegal value. */ - EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ - EADDRINUSE, /* ERR_USE -8 Address in use. */ - EALREADY, /* ERR_ALREADY -9 Already connecting. */ - EISCONN, /* ERR_ISCONN -10 Conn already established.*/ - ENOTCONN, /* ERR_CONN -11 Not connected. */ - -1, /* ERR_IF -12 Low-level netif error */ - ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ - ECONNRESET, /* ERR_RST -14 Connection reset. */ - ENOTCONN, /* ERR_CLSD -15 Connection closed. */ - EIO /* ERR_ARG -16 Illegal argument. */ -}; - -#define ERR_TO_ERRNO_TABLE_SIZE LWIP_ARRAYSIZE(err_to_errno_table) - -#define err_to_errno(err) \ - ((unsigned)(-(signed)(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ - err_to_errno_table[-(signed)(err)] : EIO) - #if LWIP_SOCKET_SET_ERRNO #ifndef set_errno #define set_errno(err) do { if (err) { errno = (err); } } while(0) @@ -972,8 +941,6 @@ int lwip_sendmsg(int s, const struct msghdr *msg, int flags) { struct lwip_sock *sock; - struct netbuf *chain_buf; - u16_t remote_port; int i; #if LWIP_TCP u8_t write_flags; @@ -1030,82 +997,85 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags) } /* else, UDP and RAW NETCONNs */ #if LWIP_UDP || LWIP_RAW + { + struct netbuf *chain_buf; - LWIP_UNUSED_ARG(flags); - LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || - IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - /* initialize chain buffer with destination */ - chain_buf = netbuf_new(); - if (!chain_buf) { - sock_set_errno(sock, err_to_errno(ERR_MEM)); - return -1; - } - if (msg->msg_name) { - SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); - netbuf_fromport(chain_buf) = remote_port; - } + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + u16_t remote_port; + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } #if LWIP_NETIF_TX_SINGLE_PBUF - for (i = 0; i < msg->msg_iovlen; i++) { - size += msg->msg_iov[i].iov_len; - } - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { - err = ERR_MEM; - } - else { - /* flatten the IO vectors */ - size_t offset = 0; for (i = 0; i < msg->msg_iovlen; i++) { - MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); - offset += msg->msg_iov[i].iov_len; + size += msg->msg_iov[i].iov_len; } -#if LWIP_CHECKSUM_ON_COPY - { - /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ - u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); - netbuf_set_chksum(chain_buf, chksum); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - err = ERR_OK; - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain - manually to avoid having to allocate, chain, and delete a netbuf for each iov */ - for (i = 0; i < msg->msg_iovlen; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (p == NULL) { - err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ - break; - } - p->payload = msg->msg_iov[i].iov_base; - LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); - p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; - /* netbuf empty, add new pbuf */ - if (chain_buf->p == NULL) { - chain_buf->p = chain_buf->ptr = p; - /* add pbuf to existing pbuf chain */ + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; } else { - pbuf_cat(chain_buf->p, p); + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); } - } - /* save size of total chain */ - if (err == ERR_OK) { - size = netbuf_len(chain_buf); - } #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (err == ERR_OK) { - /* send the data */ - err = netconn_send(sock->conn, chain_buf); + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); } - - /* deallocated the buffer */ - netbuf_delete(chain_buf); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? size : -1); #else /* LWIP_UDP || LWIP_RAW */ sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1; @@ -1288,12 +1258,12 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt) * the sockets enabled that had events. * * @param maxfdp1 the highest socket index in the sets - * @param readset_in: set of sockets to check for read events - * @param writeset_in: set of sockets to check for write events - * @param exceptset_in: set of sockets to check for error events - * @param readset_out: set of sockets that had read events - * @param writeset_out: set of sockets that had write events - * @param exceptset_out: set os sockets that had error events + * @param readset_in set of sockets to check for read events + * @param writeset_in set of sockets to check for write events + * @param exceptset_in set of sockets to check for error events + * @param readset_out set of sockets that had read events + * @param writeset_out set of sockets that had write events + * @param exceptset_out set os sockets that had error events * @return number of sockets that had events (read/write/exception) (>= 0) */ static int @@ -1832,7 +1802,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) /* write back optlen and optval */ *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; #if LWIP_MPU_COMPATIBLE - memcpy(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); #endif /* LWIP_MPU_COMPATIBLE */ @@ -2022,7 +1992,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { return ENOPROTOOPT; } - *(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl; + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", s, *(int *)optval)); break; @@ -2220,7 +2190,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; #if LWIP_MPU_COMPATIBLE - memcpy(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); + MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); #else /* LWIP_MPU_COMPATIBLE */ LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; #endif /* LWIP_MPU_COMPATIBLE */ @@ -2389,7 +2359,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_ #if LWIP_MULTICAST_TX_OPTIONS case IP_MULTICAST_TTL: LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); - sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); break; case IP_MULTICAST_IF: { @@ -2732,14 +2702,16 @@ lwip_fcntl(int s, int cmd, int val) static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) { - /* s+1 is stored in the array to prevent having to initialize the array - (default initialization is to 0) */ - int sa = s + 1; + struct lwip_sock *sock = get_socket(s); int i; + if (!sock) { + return 0; + } + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sa == 0) { - socket_ipv4_multicast_memberships[i].sa = sa; + if (socket_ipv4_multicast_memberships[i].sock == NULL) { + socket_ipv4_multicast_memberships[i].sock = sock; ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); return 1; @@ -2756,16 +2728,18 @@ lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) { - /* s+1 is stored in the array to prevent having to initialize the array - (default initialization is to 0) */ - int sa = s + 1; + struct lwip_sock *sock = get_socket(s); int i; + if (!sock) { + return; + } + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if ((socket_ipv4_multicast_memberships[i].sa == sa) && + if ((socket_ipv4_multicast_memberships[i].sock == sock) && ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { - socket_ipv4_multicast_memberships[i].sa = 0; + socket_ipv4_multicast_memberships[i].sock = NULL; ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); return; @@ -2777,21 +2751,22 @@ lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_ad * * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). */ -static void lwip_socket_drop_registered_memberships(int s) +static void +lwip_socket_drop_registered_memberships(int s) { - /* s+1 is stored in the array to prevent having to initialize the array - (default initialization is to 0) */ - int sa = s + 1; + struct lwip_sock *sock = get_socket(s); int i; - LWIP_ASSERT("socket has no netconn", sockets[s].conn != NULL); + if (!sock) { + return; + } for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sa == sa) { + if (socket_ipv4_multicast_memberships[i].sock == sock) { ip_addr_t multi_addr, if_addr; ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); - socket_ipv4_multicast_memberships[i].sa = 0; + socket_ipv4_multicast_memberships[i].sock = NULL; ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 5ab26584..07b2f984 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -48,6 +48,7 @@ #include "lwip/ip.h" #include "lwip/pbuf.h" #include "lwip/etharp.h" +#include "netif/ethernet.h" #define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) #define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) @@ -64,6 +65,13 @@ static sys_mbox_t mbox; sys_mutex_t lock_tcpip_core; #endif /* LWIP_TCPIP_CORE_LOCKING */ +#if LWIP_TIMERS +/* wait for a message, timeouts are processed while waiting */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg) +#else /* LWIP_TIMERS */ +/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg) +#endif /* LWIP_TIMERS */ /** * The main lwIP thread. This thread has exclusive access to lwIP core functions @@ -90,7 +98,7 @@ tcpip_thread(void *arg) UNLOCK_TCPIP_CORE(); LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ - sys_timeouts_mbox_fetch(&mbox, (void **)&msg); + TCPIP_MBOX_FETCH(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); if (msg == NULL) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); @@ -118,7 +126,7 @@ tcpip_thread(void *arg) break; #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ -#if LWIP_TCPIP_TIMEOUT +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS case TCPIP_MSG_TIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); @@ -129,7 +137,7 @@ tcpip_thread(void *arg) sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; -#endif /* LWIP_TCPIP_TIMEOUT */ +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); @@ -248,11 +256,11 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) return ERR_OK; } -#if LWIP_TCPIP_TIMEOUT +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS /** * call sys_timeout in tcpip_thread * - * @param msec time in milliseconds for timeout + * @param msecs time in milliseconds for timeout * @param h function to be called on timeout * @param arg argument to pass to timeout function h * @return ERR_MEM on memory error, ERR_OK otherwise @@ -280,7 +288,6 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) /** * call sys_untimeout in tcpip_thread * - * @param msec time in milliseconds for timeout * @param h function to be called on timeout * @param arg argument to pass to timeout function h * @return ERR_MEM on memory error, ERR_OK otherwise @@ -303,7 +310,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg) sys_mbox_post(&mbox, msg); return ERR_OK; } -#endif /* LWIP_TCPIP_TIMEOUT */ +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ /** @@ -374,7 +381,7 @@ tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) #endif /* LWIP_NETCONN_SEM_PER_THREAD */ LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - + TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; diff --git a/src/apps/httpd/httpd.c b/src/apps/httpd/httpd.c index 6be2573e..103f9acb 100644 --- a/src/apps/httpd/httpd.c +++ b/src/apps/httpd/httpd.c @@ -337,82 +337,6 @@ char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each ext static struct http_state *http_connections; #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ -#if LWIP_HTTPD_STRNSTR_PRIVATE -/** Like strstr but does not need 'buffer' to be NULL-terminated */ -static char* -strnstr(const char* buffer, const char* token, size_t n) -{ - const char* p; - int tokenlen = (int)strlen(token); - if (tokenlen == 0) { - return (char *)(size_t)buffer; - } - for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { - if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { - return (char *)(size_t)p; - } - } - return NULL; -} -#endif /* LWIP_HTTPD_STRNSTR_PRIVATE */ - -#if LWIP_HTTPD_STRICMP_PRIVATE -static int -stricmp(const char* str1, const char* str2) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (c1 != 0); - return 0; -} -#endif /* LWIP_HTTPD_STRICMP_PRIVATE */ - -#if LWIP_HTTPD_ITOA_PRIVATE && LWIP_HTTPD_DYNAMIC_HEADERS -static void -httpd_itoa(int value, char* result) -{ - const int base = 10; - char* ptr = result, *ptr1 = result, tmp_char; - int tmp_value; - - do { - tmp_value = value; - value /= base; - *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)]; - } while(value); - - /* Apply negative sign */ - if (tmp_value < 0) { - *ptr++ = '-'; - } - *ptr-- = '\0'; - while(ptr1 < ptr) { - tmp_char = *ptr; - *ptr--= *ptr1; - *ptr1++ = tmp_char; - } -} -#endif - #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED static void http_kill_oldest_connection(u8_t ssi_required) @@ -964,7 +888,7 @@ get_http_headers(struct http_state *hs, const char *uri) /* Now determine the content type and add the relevant header for that. */ for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { /* Have we found a matching extension? */ - if(!stricmp(g_psHTTPHeaders[content_type].extension, ext)) { + if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { break; } } @@ -1012,7 +936,7 @@ get_http_headers(struct http_state *hs, const char *uri) } if (add_content_len) { size_t len; - LWIP_HTTPD_ITOA(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, + lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, hs->handle->len); len = strlen(hs->hdr_content_len); if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { @@ -1112,7 +1036,7 @@ http_send_headers(struct tcp_pcb *pcb, struct http_state *hs) * (which would happen when sending files from async read). */ if(http_check_eof(pcb, hs)) { data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } + } } /* If we get here and there are still header bytes to send, we send * the header information we just wrote immediately. If there are no @@ -1553,6 +1477,8 @@ http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs) } } break; + default: + break; } } } @@ -1802,16 +1728,16 @@ http_post_request(struct pbuf *inp, struct http_state *hs, { err_t err; /* search for end-of-header (first double-CRLF) */ - char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); + char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); if (crlfcrlf != NULL) { /* search for "Content-Length: " */ #define HTTP_HDR_CONTENT_LEN "Content-Length: " #define HTTP_HDR_CONTENT_LEN_LEN 16 #define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 - char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); + char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); if (scontent_len != NULL) { - char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); + char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); if (scontent_len_end != NULL) { int content_len; char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; @@ -1953,7 +1879,7 @@ http_continue(void *connection) * When data has been received in the correct state, try to parse it * as a HTTP request. * - * @param p the received pbuf + * @param inp the received pbuf * @param hs the connection state * @param pcb the tcp_pcb which received this packet * @return ERR_OK if request was OK and hs has been initialized correctly @@ -2020,7 +1946,7 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) /* received enough data for minimal request? */ if (data_len >= MIN_REQ_LEN) { /* wait for CRLF before parsing anything */ - crlf = strnstr(data, CRLF, data_len); + crlf = lwip_strnstr(data, CRLF, data_len); if (crlf != NULL) { #if LWIP_HTTPD_SUPPORT_POST int is_post = 0; @@ -2052,11 +1978,11 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) } /* if we come here, method is OK, parse URI */ left_len = (u16_t)(data_len - ((sp1 +1) - data)); - sp2 = strnstr(sp1 + 1, " ", left_len); + sp2 = lwip_strnstr(sp1 + 1, " ", left_len); #if LWIP_HTTPD_SUPPORT_V09 if (sp2 == NULL) { /* HTTP 0.9: respond with correct protocol version */ - sp2 = strnstr(sp1 + 1, CRLF, left_len); + sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); is_09 = 1; #if LWIP_HTTPD_SUPPORT_POST if (is_post) { @@ -2069,13 +1995,13 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) uri_len = (u16_t)(sp2 - (sp1 + 1)); if ((sp2 != 0) && (sp2 > sp1)) { /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ - if (strnstr(data, CRLF CRLF, data_len) != NULL) { + if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { char *uri = sp1 + 1; #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE /* This is HTTP/1.0 compatible: for strict 1.1, a connection would always be persistent unless "close" was specified. */ - if (!is_09 && (strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || - strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { + if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || + lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { hs->keepalive = 1; } else { hs->keepalive = 0; @@ -2259,7 +2185,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) } tag_check = 0; for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (!stricmp(ext, g_pcSSIExtensions[loop])) { + if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { tag_check = 1; break; } @@ -2285,7 +2211,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) * @param uri the HTTP header URI * @param tag_check enable SSI tag checking - * @param uri_has_params != NULL if URI has parameters (separated by '?') + * @param params != NULL if URI has parameters (separated by '?') * @return ERR_OK if file was found and hs has been initialized correctly * another err_t otherwise */ @@ -2334,7 +2260,7 @@ http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const cha if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { /* HTTP/0.9 responses are sent without HTTP header, search for the end of the header. */ - char *file_start = strnstr(hs->file, CRLF CRLF, hs->left); + char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); if (file_start != NULL) { size_t diff = file_start + 4 - hs->file; hs->file += diff; @@ -2584,7 +2510,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err) LWIP_UNUSED_ARG(err); LWIP_UNUSED_ARG(arg); LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg)); - + if ((err != ERR_OK) || (pcb == NULL)) { return ERR_VAL; } @@ -2684,7 +2610,7 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers) { LWIP_ASSERT("no cgis given", cgis != NULL); LWIP_ASSERT("invalid number of handlers", num_handlers > 0); - + g_pCGIs = cgis; g_iNumCGIs = num_handlers; } diff --git a/src/apps/httpd/makefsdata/makefsdata.c b/src/apps/httpd/makefsdata/makefsdata.c index 34101a48..934e7219 100644 --- a/src/apps/httpd/makefsdata/makefsdata.c +++ b/src/apps/httpd/makefsdata/makefsdata.c @@ -2,7 +2,7 @@ * makefsdata: Converts a directory structure for use with the lwIP httpd. * * This file is part of the lwIP TCP/IP stack. - * + * * Author: Jim Pettinato * Simon Goldschmidt * @@ -818,7 +818,7 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size, u8_t provide_last_modified = includeLastModified; memset(hdr_buf, 0, sizeof(hdr_buf)); - + if (useHttp11) { response_type = HTTP_HDR_OK_11; } diff --git a/src/apps/lwiperf/lwiperf.c b/src/apps/lwiperf/lwiperf.c index 06868676..1996cd1a 100644 --- a/src/apps/lwiperf/lwiperf.c +++ b/src/apps/lwiperf/lwiperf.c @@ -262,7 +262,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) /* this session is time-limited */ u32_t now = sys_now(); u32_t diff_ms = now - conn->time_started; - u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount); + u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount); u32_t time_ms = time * 10; if (diff_ms >= time_ms) { /* time specified by the client is over -> close the connection */ @@ -271,7 +271,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) } } else { /* this session is byte-limited */ - u32_t amount_bytes = htonl(conn->settings.amount); + u32_t amount_bytes = lwip_htonl(conn->settings.amount); /* @todo: this can send up to 1*MSS more than requested... */ if (amount_bytes >= conn->bytes_transferred) { /* all requested bytes transferred -> close the connection */ @@ -374,7 +374,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn) return ERR_MEM; } - memcpy(client_conn, conn, sizeof(lwiperf_state_tcp_t)); + MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t)); client_conn->base.server = 0; client_conn->server_pcb = NULL; client_conn->conn_pcb = newpcb; @@ -390,7 +390,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn) tcp_err(newpcb, lwiperf_tcp_err); ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); - remote_port = (u16_t)htonl(client_conn->settings.remote_port); + remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port); err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); if (err != ERR_OK) { @@ -405,6 +405,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn) static err_t lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { + u8_t tmp; u16_t tot_len; u32_t packet_idx; struct pbuf* q; @@ -470,8 +471,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) return ERR_OK; } conn->next_num = 4; /* 24 bytes received... */ - err = pbuf_header(p, -24); - LWIP_ASSERT("pbuf_header failed", err == ERR_OK); + tmp = pbuf_header(p, -24); + LWIP_ASSERT("pbuf_header failed", tmp == 0); } packet_idx = 0; @@ -578,7 +579,7 @@ lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) { - return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, + return lwiperf_start_tcp_server(IP4_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, report_fn, report_arg); } diff --git a/src/apps/mdns/mdns.c b/src/apps/mdns/mdns.c new file mode 100644 index 00000000..e0c528c3 --- /dev/null +++ b/src/apps/mdns/mdns.c @@ -0,0 +1,2031 @@ +/** + * @file + * MDNS responder implementation + * + * @defgroup mdns MDNS + * @ingroup apps + * + * RFC 6762 - Multicast DNS\n + * RFC 6763 - DNS-Based Service Discovery\n + * + * @verbinclude mdns.txt + * + * Things left to implement: + * ------------------------- + * + * - Probing/conflict resolution + * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... + * - Checking that source address of unicast requests are on the same network + * - Limiting multicast responses to 1 per second per resource record + * - Fragmenting replies if required + * - Subscribe to netif address/link change events and act on them (currently needs to be done manually) + * - Handling multi-packet known answers + * - Individual known answer detection for all local IPv6 addresses + * - Dynamic size of outgoing packet + */ + +/* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + * Please coordinate changes and requests with Erik Ekman + * + * + */ + +#include "lwip/apps/mdns.h" +#include "lwip/apps/mdns_priv.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/prot/dns.h" + +#include +#include + +#if LWIP_MDNS_RESPONDER + +#if (LWIP_IPV4 && !LWIP_IGMP) + #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" +#endif +#if (LWIP_IPV6 && !LWIP_IPV6_MLD) +#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP) + #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif + +#if LWIP_IPV4 +#include "lwip/igmp.h" +/* IPv4 multicast group 224.0.0.251 */ +static const ip_addr_t v4group = IPADDR4_INIT(PP_HTONL(0xE00000FBUL)); +#endif + +#if LWIP_IPV6 +#include "lwip/mld6.h" +/* IPv6 multicast group FF02::FB */ +static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x000000FBUL)); +#endif + +#define MDNS_PORT 5353 +#define MDNS_TTL 255 + +/* Stored offsets to beginning of domain names + * Used for compression. + */ +#define NUM_DOMAIN_OFFSETS 10 +#define DOMAIN_JUMP_SIZE 2 +#define DOMAIN_JUMP 0xc000 + +static u8_t mdns_netif_client_id; +static struct udp_pcb *mdns_pcb; + +#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) + +#define TOPDOMAIN_LOCAL "local" + +#define REVERSE_PTR_TOPDOMAIN "arpa" +#define REVERSE_PTR_V4_DOMAIN "in-addr" +#define REVERSE_PTR_V6_DOMAIN "ip6" + +#define SRV_PRIORITY 0 +#define SRV_WEIGHT 0 + +/* Payload size allocated for each outgoing UDP packet */ +#define OUTPACKET_SIZE 500 + +/* Lookup from hostname -> IPv4 */ +#define REPLY_HOST_A 0x01 +/* Lookup from IPv4/v6 -> hostname */ +#define REPLY_HOST_PTR_V4 0x02 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_AAAA 0x04 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_PTR_V6 0x08 + +/* Lookup for service types */ +#define REPLY_SERVICE_TYPE_PTR 0x10 +/* Lookup for instances of service */ +#define REPLY_SERVICE_NAME_PTR 0x20 +/* Lookup for location of service instance */ +#define REPLY_SERVICE_SRV 0x40 +/* Lookup for text info on service instance */ +#define REPLY_SERVICE_TXT 0x80 + +static const char *dnssd_protos[] = { + "_udp", /* DNSSD_PROTO_UDP */ + "_tcp", /* DNSSD_PROTO_TCP */ +}; + +/** Description of a service */ +struct mdns_service { + /** TXT record to answer with */ + struct mdns_domain txtdata; + /** Name of service, like 'myweb' */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Type of service, like '_http' */ + char service[MDNS_LABEL_MAXLEN + 1]; + /** Callback function and userdata + * to update txtdata buffer */ + service_get_txt_fn_t txt_fn; + void *txt_userdata; + /** TTL in seconds of SRV/TXT replies */ + u32_t dns_ttl; + /** Protocol, TCP or UDP */ + u16_t proto; + /** Port of the service */ + u16_t port; +}; + +/** Description of a host/netif */ +struct mdns_host { + /** Hostname */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Pointer to services */ + struct mdns_service *services[MDNS_MAX_SERVICES]; + /** TTL in seconds of A/AAAA/PTR replies */ + u32_t dns_ttl; +}; + +/** Information about received packet */ +struct mdns_packet { + /** Sender IP/port */ + ip_addr_t source_addr; + u16_t source_port; + /** If packet was received unicast */ + u16_t recv_unicast; + /** Netif that received the packet */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current parsing offset in packet */ + u16_t parse_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Number of questions in packet, + * read from packet header */ + u16_t questions; + /** Number of unparsed questions */ + u16_t questions_left; + /** Number of answers in packet, + * (sum of normal, authorative and additional answers) + * read from packet header */ + u16_t answers; + /** Number of unparsed answers */ + u16_t answers_left; +}; + +/** Information about outgoing packet */ +struct mdns_outpacket { + /** Netif to send the packet on */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current write offset in packet */ + u16_t write_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Destination IP/port if sent unicast */ + ip_addr_t dest_addr; + u16_t dest_port; + /** Number of questions written */ + u16_t questions; + /** Number of normal answers written */ + u16_t answers; + /** Number of additional answers written */ + u16_t additional; + /** Offsets for written domain names in packet. + * Used for compression */ + u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; + /** If all answers in packet should set cache_flush bit */ + u8_t cache_flush; + /** If reply should be sent unicast */ + u8_t unicast_reply; + /** If legacy query. (tx_id needed, and write + * question again in reply before answer) */ + u8_t legacy_query; + /* Reply bitmask for host information */ + u8_t host_replies; + /* Bitmask for which reverse IPv6 hosts to answer */ + u8_t host_reverse_v6_replies; + /* Reply bitmask per service */ + u8_t serv_replies[MDNS_MAX_SERVICES]; +}; + +/** Domain, type and class. + * Shared between questions and answers */ +struct mdns_rr_info { + struct mdns_domain domain; + u16_t type; + u16_t klass; +}; + +struct mdns_question { + struct mdns_rr_info info; + /** unicast reply requested */ + u16_t unicast; +}; + +struct mdns_answer { + struct mdns_rr_info info; + /** cache flush command bit */ + u16_t cache_flush; + /* Validity time in seconds */ + u32_t ttl; + /** Length of variable answer */ + u16_t rd_length; + /** Offset of start of variable answer in packet */ + u16_t rd_offset; +}; + +/** + * Add a label part to a domain + * @param domain The domain to add a label to + * @param label The label to add, like <hostname>, 'local', 'com' or '' + * @param len The length of the label + * @return ERR_OK on success, an err_t otherwise if label too long + */ +err_t +mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) +{ + if (len > MDNS_LABEL_MAXLEN) { + return ERR_VAL; + } + if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + /* Allow only zero marker on last byte */ + if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + domain->name[domain->length] = len; + domain->length++; + if (len) { + MEMCPY(&domain->name[domain->length], label, len); + domain->length += len; + } + return ERR_OK; +} + +/** + * Internal readname function with max 6 levels of recursion following jumps + * while decompressing name + */ +static u16_t +mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) +{ + u8_t c; + + do { + if (depth > 5) { + /* Too many jumps */ + return MDNS_READNAME_ERROR; + } + + c = pbuf_get_at(p, offset); + offset++; + + /* is this a compressed label? */ + if((c & 0xc0) == 0xc0) { + u16_t jumpaddr; + if (offset >= p->tot_len) { + /* Make sure both jump bytes fit in the packet */ + return MDNS_READNAME_ERROR; + } + jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); + offset++; + if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { + u16_t res; + /* Recursive call, maximum depth will be checked */ + res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); + /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ + if (res == MDNS_READNAME_ERROR) { + return res; + } + } else { + return MDNS_READNAME_ERROR; + } + break; + } + + /* normal label */ + if (c <= MDNS_LABEL_MAXLEN) { + u8_t label[MDNS_LABEL_MAXLEN]; + err_t res; + + if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { + return MDNS_READNAME_ERROR; + } + if (c != 0) { + if (pbuf_copy_partial(p, label, c, offset) != c) { + return MDNS_READNAME_ERROR; + } + offset += c; + } + res = mdns_domain_add_label(domain, (char *) label, c); + if (res != ERR_OK) { + return MDNS_READNAME_ERROR; + } + } else { + /* bad length byte */ + return MDNS_READNAME_ERROR; + } + } while (c != 0); + + return offset; +} + +/** + * Read possibly compressed domain name from packet buffer + * @param p The packet + * @param offset start position of domain name in packet + * @param domain The domain name destination + * @return The new offset after the domain, or MDNS_READNAME_ERROR + * if reading failed + */ +u16_t +mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) +{ + memset(domain, 0, sizeof(struct mdns_domain)); + return mdns_readname_loop(p, offset, domain, 0); +} + +/** + * Print domain name to debug output + * @param domain The domain name + */ +static void +mdns_domain_debug_print(struct mdns_domain *domain) +{ + u8_t *src = domain->name; + u8_t i; + + while (*src) { + u8_t label_len = *src; + src++; + for (i = 0; i < label_len; i++) { + LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); + } + src += label_len; + LWIP_DEBUGF(MDNS_DEBUG, (".")); + } +} + +/** + * Return 1 if contents of domains match (case-insensitive) + * @param a Domain name to compare 1 + * @param b Domain name to compare 2 + * @return 1 if domains are equal ignoring case, 0 otherwise + */ +int +mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) +{ + u8_t *ptra, *ptrb; + u8_t len; + int res; + + if (a->length != b->length) { + return 0; + } + + ptra = a->name; + ptrb = b->name; + while (*ptra && *ptrb && ptra < &a->name[a->length]) { + if (*ptra != *ptrb) { + return 0; + } + len = *ptra; + ptra++; + ptrb++; + res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); + if (res != 0) { + return 0; + } + ptra += len; + ptrb += len; + } + if (*ptra != *ptrb && ptra < &a->name[a->length]) { + return 0; + } + return 1; +} + +/** + * Call user supplied function to setup TXT data + * @param service The service to build TXT record for + */ +static void +mdns_prepare_txtdata(struct mdns_service *service) +{ + memset(&service->txtdata, 0, sizeof(struct mdns_domain)); + if (service->txt_fn) { + service->txt_fn(service, service->txt_userdata); + } +} + +#if LWIP_IPV4 +/** + * Build domain for reverse lookup of IPv4 address + * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 + * @param domain Where to write the domain name + * @param addr Pointer to an IPv4 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { + char buf[4]; + u8_t val = ptr[i]; + + lwip_itoa(buf, sizeof(buf), val); + res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +#if LWIP_IPV6 +/** + * Build domain for reverse lookup of IP address + * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab + * @param domain Where to write the domain name + * @param addr Pointer to an IPv6 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) { + char buf; + u8_t byte = ptr[i]; + int j; + for (j = 0; j < 2; j++) { + if ((byte & 0x0F) < 0xA) { + buf = '0' + (byte & 0x0F); + } else { + buf = 'a' + (byte & 0x0F) - 0xA; + } + res = mdns_domain_add_label(domain, &buf, sizeof(buf)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + byte >>= 4; + } + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +/* Add .local. to domain */ +static err_t +mdns_add_dotlocal(struct mdns_domain *domain) +{ + err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1)); + LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); + return mdns_domain_add_label(domain, NULL, 0); +} + +/** + * Build the .local. domain name + * @param domain Where to write the domain name + * @param mdns TMDNS netif descriptor. + * @return ERR_OK if domain .local. was written, an err_t otherwise + */ +static err_t +mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); + res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); + LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build the lookup-all-services special DNS-SD domain name + * @param domain Where to write the domain name + * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise + */ +static err_t +mdns_build_dnssd_domain(struct mdns_domain *domain) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build domain name for a service + * @param domain Where to write the domain name + * @param service The service struct, containing service name, type and protocol + * @param include_name Whether to include the service name in the domain + * @return ERR_OK if domain was written. If service name is included, + * ...local. will be written, otherwise ..local. + * An err_t is returned on error. + */ +static err_t +mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + if (include_name) { + res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Check which replies we should send for a host/netif based on question + * @param netif The network interface that received the question + * @param rr Domain/type/class from a question + * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for + * if reply bit has REPLY_HOST_PTR_V6 set + * @return Bitmask of which replies to send + */ +static int +check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return replies; + } + + /* Handle PTR for our addresses */ + if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { +#if LWIP_IPV6 + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V6; + /* Mark which addresses where requested */ + if (reverse_v6_reply) { + *reverse_v6_reply |= (1 << i); + } + } + } + } +#endif +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { + res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V4; + } + } +#endif + } + + res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); + /* Handle requests for our hostname */ + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* TODO return NSEC if unsupported protocol requested */ +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) + && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { + replies |= REPLY_HOST_A; + } +#endif +#if LWIP_IPV6 + if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_HOST_AAAA; + } +#endif + } + + return replies; +} + +/** + * Check which replies we should send for a service based on question + * @param service A registered MDNS service + * @param rr Domain/type/class from a question + * @return Bitmask of which replies to send + */ +static int +check_service(struct mdns_service *service, struct mdns_rr_info *rr) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return 0; + } + + res = mdns_build_dnssd_domain(&mydomain); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for all service types */ + replies |= REPLY_SERVICE_TYPE_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 0); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for the instance of my service */ + replies |= REPLY_SERVICE_NAME_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 1); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* Request for info about my service */ + if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_SRV; + } + if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_TXT; + } + } + + return replies; +} + +/** + * Return bytes needed to write before jump for best result of compressing supplied domain + * against domain in outpacket starting at specified offset. + * If a match is found, offset is updated to where to jump to + * @param pbuf Pointer to pbuf with the partially constructed DNS packet + * @param offset Start position of a domain written earlier. If this location is suitable + * for compression, the pointer is updated to where in the domain to jump to. + * @param domain The domain to write + * @return Number of bytes to write of the new domain before writing a jump to the offset. + * If compression can not be done against this previous domain name, the full new + * domain length is returned. + */ +u16_t +mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) +{ + struct mdns_domain target; + u16_t target_end; + u8_t target_len; + u8_t writelen = 0; + u8_t *ptr; + if (pbuf == NULL) { + return domain->length; + } + target_end = mdns_readname(pbuf, *offset, &target); + if (target_end == MDNS_READNAME_ERROR) { + return domain->length; + } + target_len = (u8_t)(target_end - *offset); + ptr = domain->name; + while (writelen < domain->length) { + u8_t domainlen = (u8_t)(domain->length - writelen); + u8_t labellen; + if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { + /* Compare domains if target is long enough, and we have enough left of the domain */ + u8_t targetpos = (u8_t)(target.length - domainlen); + if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { + /* We are checking at or beyond a jump in the original, stop looking */ + break; + } + if (target.length >= domainlen && + memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { + *offset += targetpos; + return writelen; + } + } + /* Skip to next label in domain */ + labellen = *ptr; + writelen += 1 + labellen; + ptr += 1 + labellen; + } + /* Nothing found */ + return domain->length; +} + +/** + * Write domain to outpacket. Compression will be attempted, + * unless domain->skip_compression is set. + * @param outpkt The outpacket to write to + * @param domain The domain name to write + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) +{ + int i; + err_t res; + u16_t writelen = domain->length; + u16_t jump_offset = 0; + u16_t jump; + + if (!domain->skip_compression) { + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + u16_t offset = outpkt->domain_offsets[i]; + if (offset) { + u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); + if (len < writelen) { + writelen = len; + jump_offset = offset; + } + } + } + } + + if (writelen) { + /* Write uncompressed part of name */ + res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + + /* Store offset of this new domain */ + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + if (outpkt->domain_offsets[i] == 0) { + outpkt->domain_offsets[i] = outpkt->write_offset; + break; + } + } + + outpkt->write_offset += writelen; + } + if (jump_offset) { + /* Write jump */ + jump = lwip_htons(DOMAIN_JUMP | jump_offset); + res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += DOMAIN_JUMP_SIZE; + } + return ERR_OK; +} + +/** + * Write a question to an outpacket + * A question contains domain, type and class. Since an answer also starts with these fields this function is also + * called from mdns_add_answer(). + * @param outpkt The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param unicast If highest bit in class should be set, to instruct the responder to + * reply with a unicast packet + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) +{ + u16_t question_len; + u16_t field16; + err_t res; + + if (!outpkt->pbuf) { + /* If no pbuf is active, allocate one */ + outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!outpkt->pbuf) { + return ERR_MEM; + } + outpkt->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain string might be compressed */ + question_len = domain->length + sizeof(type) + sizeof(klass); + if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Write name */ + res = mdns_write_domain(outpkt, domain); + if (res != ERR_OK) { + return res; + } + + /* Write type */ + field16 = lwip_htons(type); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + /* Write class */ + if (unicast) { + klass |= 0x8000; + } + field16 = lwip_htons(klass); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + return ERR_OK; +} + +/** + * Write answer to reply packet. + * buf or answer_domain can be null. The rd_length written will be buf_length + + * size of (compressed) domain. Most uses will need either buf or answer_domain, + * special case is SRV that starts with 3 u16 and then a domain name. + * @param reply The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param cache_flush If highest bit in class should be set, to instruct receiver that + * this reply replaces any earlier answer for this domain/type/class + * @param ttl Validity time in seconds to send out for IP address data in DNS replies + * @param buf Pointer to buffer of answer data + * @param buf_length Length of variable data + * @param answer_domain A domain to write after any buffer data as answer + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, + u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) +{ + u16_t answer_len; + u16_t field16; + u16_t rdlen_offset; + u16_t answer_offset; + u32_t field32; + err_t res; + + if (!reply->pbuf) { + /* If no pbuf is active, allocate one */ + reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!reply->pbuf) { + return ERR_MEM; + } + reply->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain strings might be compressed */ + answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; + if (buf) { + answer_len += (u16_t)buf_length; + } + if (answer_domain) { + answer_len += answer_domain->length; + } + if (reply->write_offset + answer_len > reply->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Answer starts with same data as question, then more fields */ + mdns_add_question(reply, domain, type, klass, cache_flush); + + /* Write TTL */ + field32 = lwip_htonl(ttl); + res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += sizeof(field32); + + /* Store offsets and skip forward to the data */ + rdlen_offset = reply->write_offset; + reply->write_offset += sizeof(field16); + answer_offset = reply->write_offset; + + if (buf) { + /* Write static data */ + res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += (u16_t)buf_length; + } + + if (answer_domain) { + /* Write name answer (compressed if possible) */ + res = mdns_write_domain(reply, answer_domain); + if (res != ERR_OK) { + return res; + } + } + + /* Write rd_length after when we know the answer size */ + field16 = lwip_htons(reply->write_offset - answer_offset); + res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); + + return res; +} + +/** + * Helper function for mdns_read_question/mdns_read_answer + * Reads a domain, type and class from the packet + * @param pkt The MDNS packet to read from. The parse_offset field will be + * incremented to point to the next unparsed byte. + * @param info The struct to fill with domain, type and class + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) +{ + u16_t field16, copied; + pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); + if (pkt->parse_offset == MDNS_READNAME_ERROR) { + return ERR_VAL; + } + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->type = lwip_ntohs(field16); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->klass = lwip_ntohs(field16); + + return ERR_OK; +} + +/** + * Read a question from the packet. + * All questions have to be read before the answers. + * @param pkt The MDNS packet to read from. The questions_left field will be decremented + * and the parse_offset will be updated. + * @param question The struct to fill with question data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) +{ + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->questions_left) { + err_t res; + pkt->questions_left--; + + memset(question, 0, sizeof(struct mdns_question)); + res = mdns_read_rr_info(pkt, &question->info); + if (res != ERR_OK) { + return res; + } + + /* Extract unicast flag from class field */ + question->unicast = question->info.klass & 0x8000; + question->info.klass &= 0x7FFF; + + return ERR_OK; + } + return ERR_VAL; +} + +/** + * Read an answer from the packet + * The variable length reply is not copied, its pbuf offset and length is stored instead. + * @param pkt The MDNS packet to read. The answers_left field will be decremented and + * the parse_offset will be updated. + * @param answer The struct to fill with answer data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) +{ + /* Read questions first */ + if (pkt->questions_left) { + return ERR_VAL; + } + + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->answers_left) { + u16_t copied, field16; + u32_t ttl; + err_t res; + pkt->answers_left--; + + memset(answer, 0, sizeof(struct mdns_answer)); + res = mdns_read_rr_info(pkt, &answer->info); + if (res != ERR_OK) { + return res; + } + + /* Extract cache_flush flag from class field */ + answer->cache_flush = answer->info.klass & 0x8000; + answer->info.klass &= 0x7FFF; + + copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); + if (copied != sizeof(ttl)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->ttl = lwip_ntohl(ttl); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->rd_length = lwip_ntohs(field16); + + answer->rd_offset = pkt->parse_offset; + pkt->parse_offset += answer->rd_length; + + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_IPV4 +/** Write an IPv4 address (A) RR to outpacket */ +static err_t +mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); +} + +/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +#if LWIP_IPV6 +/** Write an IPv6 address (AAAA) RR to outpacket */ +static err_t +mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL); +} + +/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +/** Write an all-services -> servicetype PTR RR to outpacket */ +static err_t +mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_dnssd; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_dnssd_domain(&service_dnssd); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); + return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); +} + +/** Write a servicetype -> servicename PTR RR to outpacket */ +static err_t +mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_instance; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_service_domain(&service_instance, service, 1); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); + return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); +} + +/** Write a SRV RR to outpacket */ +static err_t +mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) +{ + struct mdns_domain service_instance, srvhost; + u16_t srvdata[3]; + mdns_build_service_domain(&service_instance, service, 1); + mdns_build_host_domain(&srvhost, mdns); + if (reply->legacy_query) { + /* RFC 6762 section 18.14: + * In legacy unicast responses generated to answer legacy queries, + * name compression MUST NOT be performed on SRV records. + */ + srvhost.skip_compression = 1; + } + srvdata[0] = lwip_htons(SRV_PRIORITY); + srvdata[1] = lwip_htons(SRV_WEIGHT); + srvdata[2] = lwip_htons(service->port); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); +} + +/** Write a TXT RR to outpacket */ +static err_t +mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) +{ + struct mdns_domain service_instance; + mdns_build_service_domain(&service_instance, service, 1); + mdns_prepare_txtdata(service); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); +} + +/** + * Setup outpacket as a reply to the incoming packet + */ +static void +mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) +{ + memset(out, 0, sizeof(struct mdns_outpacket)); + out->cache_flush = 1; + out->netif = in->netif; + + /* Copy source IP/port to use when responding unicast, or to choose + * which pcb to use for multicast (IPv4/IPv6) + */ + SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); + out->dest_port = in->source_port; + + if (in->source_port != MDNS_PORT) { + out->unicast_reply = 1; + out->cache_flush = 0; + if (in->questions == 1) { + out->legacy_query = 1; + out->tx_id = in->tx_id; + } + } + + if (in->recv_unicast) { + out->unicast_reply = 1; + } +} + +/** + * Send chosen answers as a reply + * + * Add all selected answers (first write will allocate pbuf) + * Add additional answers based on the selected answers + * Send the packet + */ +static void +mdns_send_outpacket(struct mdns_outpacket *outpkt) +{ + struct mdns_service *service; + err_t res; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif); + + /* Write answers to host questions */ +#if LWIP_IPV4 + if (outpkt->host_replies & REPLY_HOST_A) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + if (outpkt->host_replies & REPLY_HOST_PTR_V4) { + res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } +#endif +#if LWIP_IPV6 + if (outpkt->host_replies & REPLY_HOST_AAAA) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + } + if (outpkt->host_replies & REPLY_HOST_PTR_V6) { + u8_t rev_addrs = outpkt->host_reverse_v6_replies; + int addrindex = 0; + while (rev_addrs) { + if (rev_addrs & 1) { + res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + addrindex++; + rev_addrs >>= 1; + } + } +#endif + + /* Write answers to service questions */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { + res = mdns_add_servicetype_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + res = mdns_add_servicename_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + + /* All answers written, add additional RRs */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + /* Our service instance requested, include SRV & TXT + * if they are already not requested. */ + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + + /* If service instance, SRV, record or an IP address is requested, + * supply all addresses for the host + */ + if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || + (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { +#if LWIP_IPV6 + if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + } +#endif +#if LWIP_IPV4 + if (!(outpkt->host_replies & REPLY_HOST_A)) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } +#endif + } + } + + if (outpkt->pbuf) { + const ip_addr_t *mcast_destaddr; + struct dns_hdr hdr; + + /* Write header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; + hdr.numanswers = lwip_htons(outpkt->answers); + hdr.numextrarr = lwip_htons(outpkt->additional); + if (outpkt->legacy_query) { + hdr.numquestions = lwip_htons(1); + hdr.id = lwip_htons(outpkt->tx_id); + } + pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); + + /* Shrink packet */ + pbuf_realloc(outpkt->pbuf, outpkt->write_offset); + + if (IP_IS_V6_VAL(outpkt->dest_addr)) { +#if LWIP_IPV6 + mcast_destaddr = &v6group; +#endif + } else { +#if LWIP_IPV4 + mcast_destaddr = &v4group; +#endif + } + /* Send created packet */ + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); + if (outpkt->unicast_reply) { + udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); + } else { + udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif); + } + } + +cleanup: + if (outpkt->pbuf) { + pbuf_free(outpkt->pbuf); + outpkt->pbuf = NULL; + } +} + +/** + * Send unsolicited answer containing all our known data + * @param netif The network interface to send on + * @param destination The target address to send to (usually multicast address) + */ +static void +mdns_announce(struct netif *netif, const ip_addr_t *destination) +{ + struct mdns_outpacket announce; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(netif); + + memset(&announce, 0, sizeof(announce)); + announce.netif = netif; + announce.cache_flush = 1; +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) + announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; +#endif +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; + announce.host_reverse_v6_replies |= (1 << i); + } + } +#endif + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *serv = mdns->services[i]; + if (serv) { + announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | + REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; + } + } + + announce.dest_port = MDNS_PORT; + SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); + mdns_send_outpacket(&announce); +} + +/** + * Handle question MDNS packet + * 1. Parse all questions and set bits what answers to send + * 2. Clear pending answers if known answers are supplied + * 3. Put chosen answers in new packet and send as reply + */ +static void +mdns_handle_question(struct mdns_packet *pkt) +{ + struct mdns_service *service; + struct mdns_outpacket reply; + int replies = 0; + int i; + err_t res; + struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); + + mdns_init_outpacket(&reply, pkt); + + while (pkt->questions_left) { + struct mdns_question q; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); + mdns_domain_debug_print(&q.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); + + if (q.unicast) { + /* Reply unicast if any question is unicast */ + reply.unicast_reply = 1; + } + + reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); + replies |= reply.host_replies; + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + reply.serv_replies[i] |= check_service(service, &q.info); + replies |= reply.serv_replies[i]; + } + + if (replies && reply.legacy_query) { + /* Add question to reply packet (legacy packet only has 1 question) */ + res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); + if (res != ERR_OK) { + goto cleanup; + } + } + } + + /* Handle known answers */ + while (pkt->answers_left) { + struct mdns_answer ans; + u8_t rev_v6; + int match; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); + goto cleanup; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + + + if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { + /* Skip known answers for ANY type & class */ + continue; + } + + rev_v6 = 0; + match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); + if (match && (ans.ttl > (mdns->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + res = mdns_build_host_domain(&my_ans, mdns); + if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { +#if LWIP_IPV4 + if (match & REPLY_HOST_PTR_V4) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); + reply.host_replies &= ~REPLY_HOST_PTR_V4; + } +#endif +#if LWIP_IPV6 + if (match & REPLY_HOST_PTR_V6) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); + reply.host_reverse_v6_replies &= ~rev_v6; + if (reply.host_reverse_v6_replies == 0) { + reply.host_replies &= ~REPLY_HOST_PTR_V6; + } + } +#endif + } + } else if (match & REPLY_HOST_A) { +#if LWIP_IPV4 + if (ans.rd_length == sizeof(ip4_addr_t) && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); + reply.host_replies &= ~REPLY_HOST_A; + } +#endif + } else if (match & REPLY_HOST_AAAA) { +#if LWIP_IPV6 + if (ans.rd_length == sizeof(ip6_addr_t) && + /* TODO this clears all AAAA responses if first addr is set as known */ + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); + reply.host_replies &= ~REPLY_HOST_AAAA; + } +#endif + } + } + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + match = reply.serv_replies[i] & check_service(service, &ans.info); + if (match && (ans.ttl > (service->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + if (len != MDNS_READNAME_ERROR) { + if (match & REPLY_SERVICE_TYPE_PTR) { + res = mdns_build_service_domain(&my_ans, service, 0); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; + } + } + if (match & REPLY_SERVICE_NAME_PTR) { + res = mdns_build_service_domain(&my_ans, service, 1); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; + } + } + } + } else if (match & REPLY_SERVICE_SRV) { + /* Read and compare to my SRV record */ + u16_t field16, len, read_pos; + struct mdns_domain known_ans, my_ans; + read_pos = ans.rd_offset; + do { + /* Check priority field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { + break; + } + read_pos += len; + /* Check weight field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { + break; + } + read_pos += len; + /* Check port field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { + break; + } + read_pos += len; + /* Check host field */ + len = mdns_readname(pkt->pbuf, read_pos, &known_ans); + mdns_build_host_domain(&my_ans, mdns); + if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { + break; + } + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; + } while (0); + } else if (match & REPLY_SERVICE_TXT) { + mdns_prepare_txtdata(service); + if (service->txtdata.length == ans.rd_length && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; + } + } + } + } + } + + mdns_send_outpacket(&reply); + +cleanup: + if (reply.pbuf) { + /* This should only happen if we fail to alloc/write question for legacy query */ + pbuf_free(reply.pbuf); + reply.pbuf = NULL; + } +} + +/** + * Handle response MDNS packet + * Only prints debug for now. Will need more code to do conflict resolution. + */ +static void +mdns_handle_response(struct mdns_packet *pkt) +{ + /* Ignore all questions */ + while (pkt->questions_left) { + struct mdns_question q; + err_t res; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); + return; + } + } + + while (pkt->answers_left) { + struct mdns_answer ans; + err_t res; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + } +} + +/** + * Receive input function for MDNS packets. + * Handles both IPv4 and IPv6 UDP pcbs. + */ +static void +mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct dns_hdr hdr; + struct mdns_packet packet; + struct netif *recv_netif = ip_current_input_netif(); + u16_t offset = 0; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len)); + + if (NETIF_TO_HOST(recv_netif) == NULL) { + /* From netif not configured for MDNS */ + goto dealloc; + } + + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { + /* Too small */ + goto dealloc; + } + offset += SIZEOF_DNS_HDR; + + if (DNS_HDR_GET_OPCODE(&hdr)) { + /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ + goto dealloc; + } + + memset(&packet, 0, sizeof(packet)); + SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); + packet.source_port = port; + packet.netif = recv_netif; + packet.pbuf = p; + packet.parse_offset = offset; + packet.tx_id = lwip_ntohs(hdr.id); + packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); + packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); + +#if LWIP_IPV6 + if (IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) { + packet.recv_unicast = 1; + } + } +#endif +#if LWIP_IPV4 + if (!IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { + packet.recv_unicast = 1; + } + } +#endif + + if (hdr.flags1 & DNS_FLAG1_RESPONSE) { + mdns_handle_response(&packet); + } else { + mdns_handle_question(&packet); + } + +dealloc: + pbuf_free(p); +} + +/** + * @ingroup mdns + * Initiate MDNS responder. Will open UDP sockets on port 5353 + */ +void +mdns_resp_init(void) +{ + err_t res; + + mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); +#else + mdns_pcb->ttl = MDNS_TTL; +#endif + res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT); + LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); + udp_recv(mdns_pcb, mdns_recv, NULL); + + mdns_netif_client_id = netif_alloc_client_data_id(); +} + +/** + * @ingroup mdns + * Announce IP settings have changed on netif. + * Call this in your callback registered by netif_set_status_callback(). + * This function may go away in the future when netif supports registering + * multiple callback functions. + * @param netif The network interface where settings have changed. + */ +void +mdns_resp_netif_settings_changed(struct netif *netif) +{ + LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return); + + if (NETIF_TO_HOST(netif) == NULL) { + return; + } + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif +} + +/** + * @ingroup mdns + * Activate MDNS responder for a network interface and send announce packets. + * @param netif The network interface to activate. + * @param hostname Name to use. Queries for <hostname>.local will be answered + * with the IP addresses of the netif. The hostname will be copied, the + * given pointer can be on the stack. + * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies + * @return ERR_OK if netif was added, an err_t otherwise + */ +err_t +mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) +{ + err_t res; + struct mdns_host* mdns; + + LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + + LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); + mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host)); + LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); + + netif_set_client_data(netif, mdns_netif_client_id, mdns); + + memset(mdns, 0, sizeof(struct mdns_host)); + MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); + mdns->dns_ttl = dns_ttl; + + /* Join multicast groups */ +#if LWIP_IPV4 + res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif +#if LWIP_IPV6 + res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif + + mdns_resp_netif_settings_changed(netif); + return ERR_OK; + +cleanup: + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return res; +} + +/** + * @ingroup mdns + * Stop responding to MDNS queries on this interface, leave multicast groups, + * and free the helper structure and any of its services. + * @param netif The network interface to remove. + * @return ERR_OK if netif was removed, an err_t otherwise + */ +err_t +mdns_resp_remove_netif(struct netif *netif) +{ + int i; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *service = mdns->services[i]; + if (service) { + mem_free(service); + } + } + + /* Leave multicast groups */ +#if LWIP_IPV4 + igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); +#endif +#if LWIP_IPV6 + mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); +#endif + + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return ERR_OK; +} + +/** + * @ingroup mdns + * Add a service to the selected network interface. + * @param netif The network interface to publish this service on + * @param name The name of the service + * @param service The service type, like "_http" + * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP + * for others ("_udp") + * @param port The port the service listens to + * @param dns_ttl Validity time in seconds to send out for service data in DNS replies + * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to + * allow dynamic replies. + * @param txt_data Userdata pointer for txt_fn + * @return ERR_OK if the service was added to the netif, an err_t otherwise + */ +err_t +mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) +{ + int i; + int slot = -1; + struct mdns_service *srv; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); + + LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + if (mdns->services[i] == NULL) { + slot = i; + break; + } + } + LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); + + srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service)); + LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); + + memset(srv, 0, sizeof(struct mdns_service)); + + MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); + MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); + srv->txt_fn = txt_fn; + srv->txt_userdata = txt_data; + srv->proto = (u16_t)proto; + srv->port = port; + srv->dns_ttl = dns_ttl; + + mdns->services[slot] = srv; + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif + + return ERR_OK; +} + +/** + * @ingroup mdns + * Call this function from inside the service_get_txt_fn_t callback to add text data. + * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. + * @param service The service provided to the get_txt callback + * @param txt String to add to the TXT field. + * @param txt_len Length of string + * @return ERR_OK if the string was added to the reply, an err_t otherwise + */ +err_t +mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) +{ + LWIP_ASSERT("mdns_resp_add_service: service != NULL", service); + + /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ + return mdns_domain_add_label(&service->txtdata, txt, txt_len); +} + +#endif /* LWIP_MDNS_RESPONDER */ diff --git a/src/apps/netbiosns/netbiosns.c b/src/apps/netbiosns/netbiosns.c index dd01c026..2dfbe659 100644 --- a/src/apps/netbiosns/netbiosns.c +++ b/src/apps/netbiosns/netbiosns.c @@ -46,6 +46,7 @@ #if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ +#include "lwip/def.h" #include "lwip/udp.h" #include "lwip/netif.h" @@ -270,7 +271,7 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t /* decode the NetBIOS name */ netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); /* if the packet is for us */ - if (NETBIOS_STRCMP(netbios_name, NETBIOS_LOCAL_NAME) == 0) { + if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { struct pbuf *q; struct netbios_resp *resp; @@ -327,7 +328,7 @@ netbiosns_init(void) netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); if (netbiosns_pcb != NULL) { /* we have to be allowed to send broadcast packets! */ - netbiosns_pcb->so_options |= SOF_BROADCAST; + ip_set_option(netbiosns_pcb, SOF_BROADCAST); udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); } @@ -346,7 +347,7 @@ netbiosns_set_name(const char* hostname) if (copy_len >= NETBIOS_NAME_LEN) { copy_len = NETBIOS_NAME_LEN - 1; } - memcpy(netbiosns_local_name, hostname, copy_len + 1); + MEMCPY(netbiosns_local_name, hostname, copy_len + 1); } #endif diff --git a/src/apps/snmp/README b/src/apps/snmp/README deleted file mode 100644 index d2815ec8..00000000 --- a/src/apps/snmp/README +++ /dev/null @@ -1,38 +0,0 @@ -lwIP SNMPv2c agent -================== - -Based on SNMP stack written by Christiaan Simons - -Rewritten by Martin Hentschel and -Dirk Ziegelmeier - -Features: - - SNMPv2c support. - - Low RAM usage - no memory pools, stack only. - - MIB2 implementation is separated from SNMP stack. - - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. - - Simple and generic API for MIB implementation. - - Comfortable node types and helper functions for scalar arrays and tables. - - Counter64, bit and truthvalue datatype support. - - Callbacks for SNMP writes e.g. to implement persistency. - - Runs on two APIs: RAW and netconn. - - Async API is gone - the stack now supports netconn API instead, - so blocking operations can be done in MIB calls. - SNMP runs in a worker thread when netconn API is used. - - Simplified thread sync support for MIBs - useful when MIBs - need to access variables shared with other threads where no locking is - possible. Used in MIB2 to access lwIP stats from lwIP thread. - -MIB compiler (code generator): - - Written in C#. MIB viewer used Windows Forms. - - Developed on Windows with Visual Studio 2010. - - Can be compiled and used under Linux with http://www.monodevelop.com/. - - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) - (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). - - MIB parser, C file generation framework and LWIP code generation are cleanly - separated, which means the code may be useful as a base for code generation - of other SNMP agents. - -Notes: - - Stack and MIB compiler were used to implement a Profinet device. - Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. diff --git a/src/apps/snmp/snmp_asn1.c b/src/apps/snmp/snmp_asn1.c index e2cb02c4..f35b7604 100644 --- a/src/apps/snmp/snmp_asn1.c +++ b/src/apps/snmp/snmp_asn1.c @@ -196,10 +196,10 @@ snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, co octets_needed--; PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); } - + /* skip to low u32 */ value++; - + while (octets_needed > 1) { octets_needed--; PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); @@ -288,7 +288,7 @@ snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t /** * Returns octet count for length. * - * @param length + * @param length parameter length * @param octets_needed points to the return value */ void @@ -306,7 +306,7 @@ snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) /** * Returns octet count for an u32_t. * - * @param value + * @param value value to be encoded * @param octets_needed points to the return value * * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded @@ -332,7 +332,7 @@ snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) /** * Returns octet count for an u64_t. * - * @param value + * @param value value to be encoded * @param octets_needed points to the return value * * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded @@ -357,7 +357,7 @@ snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) /** * Returns octet count for an s32_t. * - * @param value + * @param value value to be encoded * @param octets_needed points to the return value * * @note ASN coded integers are _always_ signed. @@ -367,7 +367,7 @@ snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) { if (value < 0) { value = ~value; - } + } if (value < 0x80L) { *octets_needed = 1; } else if (value < 0x8000L) { @@ -453,7 +453,7 @@ snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tl PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); tlv->value_len <<= 8; tlv->value_len |= data; - + /* take care for special value used for indefinite length */ if (tlv->value_len == 0xFFFF) { return ERR_VAL; @@ -551,7 +551,7 @@ snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value } else { *value <<= 8; } - + *value |= data; len--; } @@ -588,7 +588,7 @@ snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value if ((len > 0) && (len < 5)) { PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); len--; - + if (data & 0x80) { /* negative, start from -1 */ *value = -1; @@ -649,7 +649,7 @@ snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u if (oid_max_len < 2) { return ERR_MEM; } - + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); len--; @@ -736,7 +736,7 @@ snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u1 return ERR_MEM; } *buf_len = len; - + while (len > 0) { PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); buf++; diff --git a/src/apps/snmp/snmp_core.c b/src/apps/snmp/snmp_core.c index 0887243c..c0418336 100644 --- a/src/apps/snmp/snmp_core.c +++ b/src/apps/snmp/snmp_core.c @@ -42,11 +42,48 @@ * The agent implements the most important MIB2 MIBs including IPv6 support * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version * whithout IPv6 statistics (TODO).\n - * Work on SNMPv3 has started, but is not finished. + * Rewritten by Martin Hentschel and + * Dirk Ziegelmeier \n + * Work on SNMPv3 has started, but is not finished.\n * * 0 Agent Capabilities * ==================== * + * Features: + * --------- + * - SNMPv2c support. + * - Low RAM usage - no memory pools, stack only. + * - MIB2 implementation is separated from SNMP stack. + * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. + * - Simple and generic API for MIB implementation. + * - Comfortable node types and helper functions for scalar arrays and tables. + * - Counter64, bit and truthvalue datatype support. + * - Callbacks for SNMP writes e.g. to implement persistency. + * - Runs on two APIs: RAW and netconn. + * - Async API is gone - the stack now supports netconn API instead, + * so blocking operations can be done in MIB calls. + * SNMP runs in a worker thread when netconn API is used. + * - Simplified thread sync support for MIBs - useful when MIBs + * need to access variables shared with other threads where no locking is + * possible. Used in MIB2 to access lwIP stats from lwIP thread. + * + * MIB compiler (code generator): + * ------------------------------ + * - Provided in lwIP contrib repository. + * - Written in C#. MIB viewer used Windows Forms. + * - Developed on Windows with Visual Studio 2010. + * - Can be compiled and used on all platforms with http://www.monodevelop.com/. + * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) + * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). + * - MIB parser, C file generation framework and LWIP code generation are cleanly + * separated, which means the code may be useful as a base for code generation + * of other SNMP agents. + * + * Notes: + * ------ + * - Stack and MIB compiler were used to implement a Profinet device. + * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. + * * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 * ------------------------------------------- * Note the S in SNMP stands for "Simple". Note that "Simple" is @@ -233,7 +270,7 @@ snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) (oid[1] > 0xFF) || (oid[2] > 0xFF) || (oid[3] > 0xFF)) { - ip4_addr_copy(*ip, *IP4_ADDR_ANY); + ip4_addr_copy(*ip, *IP4_ADDR_ANY4); return 0; } @@ -285,10 +322,10 @@ snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) return 0; } - ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); - ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); - ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); - ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); + ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); + ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); + ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); + ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); return 1; } @@ -322,9 +359,9 @@ snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) #if LWIP_IPV4 || LWIP_IPV6 /** * Convert to InetAddressType+InetAddress+InetPortNumber - * @param ip - * @param port - * @param oid + * @param ip IP address + * @param port Port + * @param oid OID * @return OID length */ u8_t @@ -335,14 +372,14 @@ snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) idx = snmp_ip_to_oid(ip, oid); oid[idx] = port; idx++; - + return idx; } /** * Convert to InetAddressType+InetAddress - * @param ip - * @param oid + * @param ip IP address + * @param oid OID * @return OID length */ u8_t @@ -375,9 +412,9 @@ snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) /** * Convert from InetAddressType+InetAddress to ip_addr_t - * @param oid - * @param oid_len - * @param ip + * @param oid OID + * @param oid_len OID length + * @param ip IP address * @return Parsed OID length */ u8_t @@ -387,7 +424,7 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) if (oid_len < 1) { return 0; } - + if (oid[0] == 0) { /* any */ /* 1x InetAddressType, 1x OID len */ if (oid_len < 2) { @@ -417,7 +454,7 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { return 0; } - + return 6; #else /* LWIP_IPV4 */ return 0; @@ -450,17 +487,17 @@ snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) /** * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t - * @param oid - * @param oid_len - * @param ip - * @param port + * @param oid OID + * @param oid_len OID length + * @param ip IP address + * @param port Port * @return Parsed OID length */ u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) { u8_t idx = 0; - + /* InetAddressType + InetAddress */ idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip); if (idx == 0) { @@ -483,10 +520,10 @@ snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) #endif /* LWIP_IPV4 || LWIP_IPV6 */ /** - * Assign an OID to \struct snmp_obj_id - * @param target - * @param oid - * @param oid_len + * Assign an OID to struct snmp_obj_id + * @param target Assignment target + * @param oid OID + * @param oid_len OID length */ void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) @@ -501,10 +538,10 @@ snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) } /** - * Prefix an OID to OID in \struct snmp_obj_id - * @param target - * @param oid - * @param oid_len + * Prefix an OID to OID in struct snmp_obj_id + * @param target Assignment target to prefix + * @param oid OID + * @param oid_len OID length */ void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) @@ -524,12 +561,12 @@ snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) } /** - * Combine two OIDs into \struct snmp_obj_id - * @param target - * @param oid1 - * @param oid1_len - * @param oid2 - * @param oid2_len + * Combine two OIDs into struct snmp_obj_id + * @param target Assignmet target + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length */ void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) @@ -539,12 +576,12 @@ snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, c } /** - * Append OIDs to \struct snmp_obj_id - * @param target - * @param oid - * @param oid_len + * Append OIDs to struct snmp_obj_id + * @param target Assignment target to append to + * @param oid OID + * @param oid_len OID length */ -void +void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) { LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); @@ -557,11 +594,11 @@ snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) /** * Compare two OIDs - * @param oid1 - * @param oid1_len - * @param oid2 - * @param oid2_len - * @return + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return -1: OID1<OID2 1: OID1 >OID2 0: equal */ s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) @@ -592,17 +629,17 @@ snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_ } /* they are equal */ - return 0; + return 0; } /** * Check of two OIDs are equal - * @param oid1 - * @param oid1_len - * @param oid2 - * @param oid2_len - * @return + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return 1: equal 0: non-equal */ u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) @@ -612,7 +649,7 @@ snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_le /** * Convert netif to interface index - * @param netif + * @param netif netif * @return index */ u8_t @@ -735,7 +772,7 @@ snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node mib = snmp_get_mib_from_oid(oid, oid_len); if (mib != NULL) { u8_t oid_instance_len; - + mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { /* get instance */ @@ -765,7 +802,7 @@ snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node return result; } -u8_t +u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance) { const struct snmp_mib *mib; @@ -791,7 +828,7 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ while ((mib != NULL) && (mn == NULL)) { u8_t oid_instance_len; - + /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); if (mn != NULL) { @@ -844,9 +881,9 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida if (node_instance->release_instance != NULL) { node_instance->release_instance(node_instance); } - /* + /* the instance itself is not valid, ask for next instance from same node. - we don't have to change any variables because node_instance->instance_oid is used as input (starting point) + we don't have to change any variables because node_instance->instance_oid is used as input (starting point) as well as output (resulting next OID), so we have to simply call get_next_instance method again */ } else { @@ -889,7 +926,7 @@ snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_valida } /* else { we found out target node } */ } else { - /* + /* there is no further (suitable) node inside this MIB, search for the next MIB with following priority 1. search for inner MIB's (whose root is located inside tree of current MIB) 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any @@ -967,11 +1004,11 @@ snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t o *oid_instance_len = oid_len - oid_offset; return (*node); } - + return NULL; } -const struct snmp_node* +const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret) { u8_t oid_offset = mib->base_oid_len; @@ -1062,7 +1099,7 @@ snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oi } } } - + return NULL; } @@ -1103,7 +1140,7 @@ snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, cons } /** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ -u8_t +u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference) { /* do not overwrite a fail result */ diff --git a/src/apps/snmp/snmp_mib2_interfaces.c b/src/apps/snmp/snmp_mib2_interfaces.c index c957a5a4..979b5073 100644 --- a/src/apps/snmp/snmp_mib2_interfaces.c +++ b/src/apps/snmp/snmp_mib2_interfaces.c @@ -58,7 +58,7 @@ /* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ -static s16_t +static s16_t interfaces_get_value(struct snmp_node_instance* instance, void* value) { if (instance->node->oid == 1) { @@ -131,7 +131,7 @@ interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; LWIP_UNUSED_ARG(column); - + /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); @@ -289,11 +289,10 @@ interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void * LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); LWIP_UNUSED_ARG(len); - if (*sint_ptr == 1 || *sint_ptr == 2) - { + if (*sint_ptr == 1 || *sint_ptr == 2) { return SNMP_ERR_NOERROR; } - + return SNMP_ERR_WRONGVALUE; } @@ -352,17 +351,17 @@ static const struct snmp_table_col_def interfaces_Table_columns[] = { #if !SNMP_SAFE_REQUESTS static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); #else static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, interfaces_Table_get_value, NULL, NULL); #endif -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ CREATE_LWIP_SYNC_NODE(1, interfaces_Number) CREATE_LWIP_SYNC_NODE(2, interfaces_Table) diff --git a/src/apps/snmp/snmp_mib2_ip.c b/src/apps/snmp/snmp_mib2_ip.c index da0e6f57..913d97f9 100644 --- a/src/apps/snmp/snmp_mib2_ip.c +++ b/src/apps/snmp/snmp_mib2_ip.c @@ -58,7 +58,7 @@ #if LWIP_IPV4 /* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ -static s16_t +static s16_t ip_get_value(struct snmp_node_instance* instance, void* value) { s32_t* sint_ptr = (s32_t*)value; @@ -146,7 +146,7 @@ ip_get_value(struct snmp_node_instance* instance, void* value) /** * Test ip object value before setting. * - * @param od is the object definition + * @param instance node instance * @param len return value space (in bytes) * @param value points to (varbind) space to copy value from. * @@ -304,7 +304,7 @@ ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_o /* fill in object properties */ return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); } - + /* not found */ return SNMP_ERR_NOSUCHINSTANCE; } @@ -326,7 +326,7 @@ ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const case 1: /* ipRouteDest */ if (default_route) { /* default rte has 0.0.0.0 dest */ - value->u32 = IP4_ADDR_ANY->addr; + value->u32 = IP4_ADDR_ANY4->addr; } else { /* netifs have netaddress dest */ ip4_addr_t tmp; @@ -378,7 +378,7 @@ ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const case 11: /* ipRouteMask */ if (default_route) { /* default rte use 0.0.0.0 mask */ - value->u32 = IP4_ADDR_ANY->addr; + value->u32 = IP4_ADDR_ANY4->addr; } else { /* other rtes use netmask */ value->u32 = netif_ip4_netmask(netif)->addr; @@ -449,7 +449,7 @@ ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_ /* check default route */ if (netif_default != NULL) { - snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[0]); + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); } @@ -464,7 +464,7 @@ ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_ snmp_ip4_to_oid(&dst, &test_oid[0]); snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); } - + netif = netif->next; } @@ -660,7 +660,7 @@ static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREAT #endif /* LWIP_ARP && LWIP_IPV4 */ #if LWIP_IPV4 -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding) CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL) CREATE_LWIP_SYNC_NODE( 3, ip_InReceives) @@ -730,7 +730,7 @@ static const struct snmp_table_simple_col_def at_Table_columns[] = { static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value); -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ CREATE_LWIP_SYNC_NODE(1, at_Table) static const struct snmp_node* const at_nodes[] = { diff --git a/src/apps/snmp/snmp_mib2_snmp.c b/src/apps/snmp/snmp_mib2_snmp.c index a991fad7..8a36d61f 100644 --- a/src/apps/snmp/snmp_mib2_snmp.c +++ b/src/apps/snmp/snmp_mib2_snmp.c @@ -188,7 +188,7 @@ snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *v return SNMP_ERR_NOERROR; } -/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ +/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ static const struct snmp_scalar_array_node_def snmp_nodes[] = { { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ diff --git a/src/apps/snmp/snmp_mib2_system.c b/src/apps/snmp/snmp_mib2_system.c index 2cf88486..90e57805 100644 --- a/src/apps/snmp/snmp_mib2_system.c +++ b/src/apps/snmp/snmp_mib2_system.c @@ -106,7 +106,7 @@ snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) * Initializes sysContact pointers * * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. + * @param ocstrlen points to string length, excluding zero terminator. * if set to NULL it is assumed that ocstr is NULL-terminated. * @param bufsize size of the buffer in bytes. * (this is required because the buffer can be overwritten by snmp-set) @@ -148,7 +148,7 @@ snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) * Initializes sysName pointers * * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. + * @param ocstrlen points to string length, excluding zero terminator. * if set to NULL it is assumed that ocstr is NULL-terminated. * @param bufsize size of the buffer in bytes. * (this is required because the buffer can be overwritten by snmp-set) @@ -189,7 +189,7 @@ snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) * Initializes sysLocation pointers * * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. + * @param ocstrlen points to string length, excluding zero terminator. * if set to NULL it is assumed that ocstr is NULL-terminated. * @param bufsize size of the buffer in bytes. * (this is required because the buffer can be overwritten by snmp-set) @@ -278,7 +278,7 @@ system_get_value(const struct snmp_scalar_array_node_def *node, void *value) return result; } -static snmp_err_t +static snmp_err_t system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) { snmp_err_t ret = SNMP_ERR_WRONGVALUE; @@ -324,7 +324,7 @@ system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void * return ret; } -static snmp_err_t +static snmp_err_t system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) { u8_t* var_wr = NULL; diff --git a/src/apps/snmp/snmp_mib2_tcp.c b/src/apps/snmp/snmp_mib2_tcp.c index db3f74ca..21f69656 100644 --- a/src/apps/snmp/snmp_mib2_tcp.c +++ b/src/apps/snmp/snmp_mib2_tcp.c @@ -58,7 +58,7 @@ /* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ -static s16_t +static s16_t tcp_get_value(struct snmp_node_instance* instance, void* value) { u32_t *uint_ptr = (u32_t*)value; @@ -154,7 +154,7 @@ static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { { 0, 0xffff } /* Port */ }; -static snmp_err_t +static snmp_err_t tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) { LWIP_UNUSED_ARG(value_len); @@ -172,7 +172,7 @@ tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, unio break; case 4: /* tcpConnRemAddress */ if (pcb->state == LISTEN) { - value->u32 = IP4_ADDR_ANY->addr; + value->u32 = IP4_ADDR_ANY4->addr; } else { value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; } @@ -212,7 +212,7 @@ tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row local_port = (u16_t)row_oid[4]; snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ remote_port = (u16_t)row_oid[9]; - + /* find tcp_pcb with requested ips and ports */ for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { pcb = *tcp_pcb_lists[i]; @@ -224,7 +224,7 @@ tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ if (pcb->state == LISTEN) { - if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY) && (remote_port == 0)) { + if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { /* fill in object properties */ return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); } @@ -261,14 +261,14 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_ pcb = *tcp_pcb_lists[i]; while (pcb != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - + if (IP_IS_V4_VAL(pcb->local_ip)) { snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); test_oid[4] = pcb->local_port; /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ if (pcb->state == LISTEN) { - snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[5]); + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); test_oid[9] = 0; } else { if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ @@ -281,7 +281,7 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_ /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); } - + pcb = pcb->next; } } @@ -301,10 +301,10 @@ tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_ /* --- tcpConnectionTable --- */ -static snmp_err_t +static snmp_err_t tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) { - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ switch (*column) { case 7: /* tcpConnectionState */ value->u32 = pcb->state + 1; @@ -336,7 +336,7 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8 if (idx == 0) { return SNMP_ERR_NOSUCHINSTANCE; } - + /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); if (idx == 0) { @@ -346,7 +346,7 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8 /* find tcp_pcb with requested ip and port*/ for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { pcb = *tcp_pcb_nonlisten_lists[i]; - + while (pcb != NULL) { if (ip_addr_cmp(&local_ip, &pcb->local_ip) && (local_port == pcb->local_port) && @@ -358,9 +358,9 @@ tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8 pcb = pcb->next; } } - + /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; + return SNMP_ERR_NOSUCHINSTANCE; } static snmp_err_t @@ -395,11 +395,11 @@ tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, idx, pcb); - + pcb = pcb->next; } } - + /* did we find a next one? */ if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); @@ -413,10 +413,10 @@ tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct /* --- tcpListenerTable --- */ -static snmp_err_t +static snmp_err_t tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) { - /* all items except tcpListenerProcess are declared as not-accessible */ + /* all items except tcpListenerProcess are declared as not-accessible */ switch (*column) { case 4: /* tcpListenerProcess */ value->u32 = 0; /* not supported */ @@ -443,7 +443,7 @@ tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t if (idx == 0) { return SNMP_ERR_NOSUCHINSTANCE; } - + /* find tcp_pcb with requested ip and port*/ pcb = tcp_listen_pcbs.listen_pcbs; while (pcb != NULL) { @@ -456,7 +456,7 @@ tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t } /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; + return SNMP_ERR_NOSUCHINSTANCE; } static snmp_err_t @@ -477,13 +477,13 @@ tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct s while (pcb != NULL) { u8_t idx = 0; u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - + /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, idx, NULL); - + pcb = pcb->next; } @@ -528,7 +528,7 @@ static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIM #endif /* LWIP_IPV4 */ static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ }; @@ -537,13 +537,13 @@ static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREA static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { - /* all items except tcpListenerProcess are declared as not-accessible */ + /* all items except tcpListenerProcess are declared as not-accessible */ { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ }; static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) diff --git a/src/apps/snmp/snmp_mib2_udp.c b/src/apps/snmp/snmp_mib2_udp.c index de1c858f..6a983df2 100644 --- a/src/apps/snmp/snmp_mib2_udp.c +++ b/src/apps/snmp/snmp_mib2_udp.c @@ -57,7 +57,7 @@ /* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ -static s16_t +static s16_t udp_get_value(struct snmp_node_instance* instance, void* value) { u32_t *uint_ptr = (u32_t*)value; @@ -91,10 +91,10 @@ udp_get_value(struct snmp_node_instance* instance, void* value) /* --- udpEndpointTable --- */ -static snmp_err_t +static snmp_err_t udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) { - /* all items except udpEndpointProcess are declared as not-accessible */ + /* all items except udpEndpointProcess are declared as not-accessible */ switch (*column) { case 8: /* udpEndpointProcess */ value->u32 = 0; /* not supported */ @@ -106,7 +106,7 @@ udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_va return SNMP_ERR_NOERROR; } -static snmp_err_t +static snmp_err_t udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) { ip_addr_t local_ip, remote_ip; diff --git a/src/apps/snmp/snmp_msg.c b/src/apps/snmp/snmp_msg.c index 48c08d5b..0cb7ca99 100644 --- a/src/apps/snmp/snmp_msg.c +++ b/src/apps/snmp/snmp_msg.c @@ -125,6 +125,7 @@ snmp_get_community_trap(void) void snmp_set_community_write(const char * const community) { + LWIP_ASSERT("community string must not be NULL", community != NULL); LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); snmp_community_write = community; } @@ -272,8 +273,7 @@ snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t } } - if (request->error_status != SNMP_ERR_NOERROR) - { + if (request->error_status != SNMP_ERR_NOERROR) { if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ @@ -323,7 +323,7 @@ snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t /** * Service an internal or external event for SNMP GET. * - * @param msg_ps points to the associated message process state + * @param request points to the associated message process state */ static err_t snmp_process_get_request(struct snmp_request *request) @@ -359,7 +359,7 @@ snmp_process_get_request(struct snmp_request *request) /** * Service an internal or external event for SNMP GET. * - * @param msg_ps points to the associated message process state + * @param request points to the associated message process state */ static err_t snmp_process_getnext_request(struct snmp_request *request) @@ -395,7 +395,7 @@ snmp_process_getnext_request(struct snmp_request *request) /** * Service an internal or external event for SNMP GETBULKT. * - * @param msg_ps points to the associated message process state + * @param request points to the associated message process state */ static err_t snmp_process_getbulk_request(struct snmp_request *request) @@ -493,7 +493,7 @@ snmp_process_getbulk_request(struct snmp_request *request) /** * Service an internal or external event for SNMP SET. * - * @param msg_ps points to the associated message process state + * @param request points to the associated message process state */ static err_t snmp_process_set_request(struct snmp_request *request) @@ -512,8 +512,7 @@ snmp_process_set_request(struct snmp_request *request) memset(&node_instance, 0, sizeof(node_instance)); request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) - { + if (request->error_status == SNMP_ERR_NOERROR) { if (node_instance.asn1_type != vb.type) { request->error_status = SNMP_ERR_WRONGTYPE; } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { @@ -528,8 +527,7 @@ snmp_process_set_request(struct snmp_request *request) node_instance.release_instance(&node_instance); } } - } - else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { /* no more varbinds in request */ break; } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { @@ -551,10 +549,8 @@ snmp_process_set_request(struct snmp_request *request) struct snmp_node_instance node_instance; memset(&node_instance, 0, sizeof(node_instance)); request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) - { - if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) - { + if (request->error_status == SNMP_ERR_NOERROR) { + if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { if (request->inbound_varbind_enumerator.varbind_count == 1) { request->error_status = SNMP_ERR_COMMITFAILED; } else { @@ -650,11 +646,12 @@ snmp_parse_inbound_frame(struct snmp_request *request) #if LWIP_SNMP_V3 if (request->version == SNMP_VERSION_3) { u16_t u16_value; + u16_t inbound_msgAuthenticationParameters_offset; /* SNMPv3 doesn't use communities */ /* @todo: Differentiate read/write access */ strcpy((char*)request->community, snmp_community); - request->community_strlen = strlen(snmp_community); + request->community_strlen = (u16_t)strlen(snmp_community); /* RFC3414 globalData */ IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); @@ -687,7 +684,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) IF_PARSE_ASSERT(parent_tlv_value_len > 0); IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_flags = s32_value; + request->msg_flags = (u8_t)s32_value; /* decode msgSecurityModel */ IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); @@ -724,7 +721,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->msg_authoritative_engine_id_len = u16_value; + request->msg_authoritative_engine_id_len = (u8_t)u16_value; /* msgAuthoritativeEngineBoots */ IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); @@ -749,7 +746,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, &u16_value, SNMP_V3_MAX_USER_LENGTH)); - request->msg_user_name_len = u16_value; + request->msg_user_name_len = (u8_t)u16_value; /* @todo: Implement unknown user error response */ IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); @@ -760,7 +757,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); IF_PARSE_ASSERT(parent_tlv_value_len > 0); /* Remember position */ - u16_t inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; + inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); /* Read auth parameters */ IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); @@ -769,18 +766,19 @@ snmp_parse_inbound_frame(struct snmp_request *request) #if LWIP_SNMP_V3_CRYPTO if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - /* Rewind stream */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); - /* Set auth parameters to zero for verification */ const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; - IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); - - /* Verify authentication */ u8_t key[20]; u8_t algo; u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; struct snmp_pbuf_stream auth_stream; + + /* Rewind stream */ + IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); + /* Set auth parameters to zero for verification */ + IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); + + /* Verify authentication */ IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); @@ -839,7 +837,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_engine_id_len = u16_value; + request->context_engine_id_len = (u8_t)u16_value; /* contextName */ IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); @@ -849,7 +847,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_name_len = u16_value; + request->context_name_len = (u8_t)u16_value; } else #endif { @@ -913,7 +911,7 @@ snmp_parse_inbound_frame(struct snmp_request *request) snmp_authfail_trap(); return ERR_ARG; } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - if (strnlen(snmp_community_write, SNMP_MAX_COMMUNITY_STR_LEN) == 0) { + if (snmp_community_write[0] == 0) { /* our write community is empty, that means all our objects are readonly */ request->error_status = SNMP_ERR_NOTWRITABLE; request->error_index = 1; @@ -1065,7 +1063,7 @@ snmp_prepare_outbound_frame(struct snmp_request *request) /* msgAuthoritativeEngineID */ snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); - memcpy(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); + MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); @@ -1140,7 +1138,7 @@ snmp_prepare_outbound_frame(struct snmp_request *request) /* contextEngineID */ snmpv3_get_engine_id(&id, &request->context_engine_id_len); - memcpy(request->context_engine_id, id, request->context_engine_id_len); + MEMCPY(request->context_engine_id, id, request->context_engine_id_len); SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); @@ -1361,6 +1359,19 @@ snmp_complete_outbound_frame(struct snmp_request *request) } } } else { + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ + switch (request->error_status) { + case SNMP_ERR_NOSUCHINSTANCE: + case SNMP_ERR_NOSUCHOBJECT: + case SNMP_ERR_ENDOFMIBVIEW: + request->error_status = SNMP_ERR_NOTWRITABLE; + break; + default: + break; + } + } + if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); @@ -1382,7 +1393,7 @@ snmp_complete_outbound_frame(struct snmp_request *request) /* Calculate padding for encryption */ if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { u8_t i; - outbound_padding = (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x03); + outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; for (i = 0; i < outbound_padding; i++) { snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0); } @@ -1517,7 +1528,7 @@ snmp_complete_outbound_frame(struct snmp_request *request) request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); - memcpy(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, @@ -1547,7 +1558,7 @@ snmp_execute_write_callbacks(struct snmp_request *request) snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ - while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == ERR_OK) { + while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); } } diff --git a/src/apps/snmp/snmp_msg.h b/src/apps/snmp/snmp_msg.h index a14b05a6..2d01ef36 100644 --- a/src/apps/snmp/snmp_msg.h +++ b/src/apps/snmp/snmp_msg.h @@ -79,11 +79,12 @@ struct snmp_varbind_enumerator u16_t varbind_count; }; -typedef u8_t snmp_vb_enumerator_err_t; -#define SNMP_VB_ENUMERATOR_ERR_OK 0 -#define SNMP_VB_ENUMERATOR_ERR_EOVB 1 -#define SNMP_VB_ENUMERATOR_ERR_ASN1ERROR 2 -#define SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH 3 +typedef enum { + SNMP_VB_ENUMERATOR_ERR_OK = 0, + SNMP_VB_ENUMERATOR_ERR_EOVB = 1, + SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, + SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 +} snmp_vb_enumerator_err_t; void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); diff --git a/src/apps/snmp/snmp_netconn.c b/src/apps/snmp/snmp_netconn.c index 7eead2e6..070b41c3 100644 --- a/src/apps/snmp/snmp_netconn.c +++ b/src/apps/snmp/snmp_netconn.c @@ -57,7 +57,7 @@ snmp_netconn_thread(void *arg) netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); #else /* LWIP_IPV6 */ conn = netconn_new(NETCONN_UDP); - netconn_bind(conn, IP_ADDR_ANY, SNMP_IN_PORT); + netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT); #endif /* LWIP_IPV6 */ LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); diff --git a/src/apps/snmp/snmp_raw.c b/src/apps/snmp/snmp_raw.c index 8cfe77a6..4a40864f 100644 --- a/src/apps/snmp/snmp_raw.c +++ b/src/apps/snmp/snmp_raw.c @@ -80,7 +80,7 @@ snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) /** * @ingroup snmp_core * Starts SNMP Agent. - * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. */ void snmp_init(void) diff --git a/src/apps/snmp/snmp_traps.c b/src/apps/snmp/snmp_traps.c index 8061766e..0d2df649 100644 --- a/src/apps/snmp/snmp_traps.c +++ b/src/apps/snmp/snmp_traps.c @@ -147,11 +147,13 @@ snmp_get_auth_traps_enabled(void) /** - * Sends an generic or enterprise specific trap message. + * @ingroup snmp_traps + * Sends a generic or enterprise specific trap message. * - * @param generic_trap is the trap code * @param eoid points to enterprise object identifier + * @param generic_trap is the trap code * @param specific_trap used for enterprise traps when generic_trap == 6 + * @param varbinds linked list of varbinds to be sent * @return ERR_OK when success, ERR_MEM if we're out of memory * * @note the use of the enterprise identifier field @@ -160,8 +162,8 @@ snmp_get_auth_traps_enabled(void) * and .iso.org.dod.internet.private.enterprises.yourenterprise * (sysObjectID) for specific traps. */ -static err_t -snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) +err_t +snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) { struct snmp_msg_trap trap_msg; struct snmp_trap_dst *td; @@ -175,10 +177,10 @@ snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_tr if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { /* lookup current source address for this dst */ if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { - if (device_enterprise_oid == NULL) { + if (eoid == NULL) { trap_msg.enterprise = snmp_get_device_enterprise_oid(); } else { - trap_msg.enterprise = device_enterprise_oid; + trap_msg.enterprise = eoid; } trap_msg.gen_trap = generic_trap; @@ -224,7 +226,7 @@ snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_tr /** * @ingroup snmp_traps - * Send generic SNMP trap + * Send generic SNMP trap */ err_t snmp_send_trap_generic(s32_t generic_trap) @@ -234,7 +236,7 @@ snmp_send_trap_generic(s32_t generic_trap) } /** - *@ingroup snmp_traps + * @ingroup snmp_traps * Send specific SNMP trap with variable bindings */ err_t @@ -295,8 +297,8 @@ snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) * Sums trap header field lengths from tail to head and * returns trap_header_lengths for second encoding pass. * + * @param trap Trap message * @param vb_len varbind-list length - * @param thl points to returned header lengths * @return the required length for encoding the trap header */ static u16_t diff --git a/src/apps/snmp/snmpv3.c b/src/apps/snmp/snmpv3.c index e5dfa321..69fb3a0a 100644 --- a/src/apps/snmp/snmpv3.c +++ b/src/apps/snmp/snmpv3.c @@ -114,8 +114,8 @@ snmpv3_build_priv_param(u8_t* priv_param) priv2 = LWIP_RAND(); } - memcpy(&priv_param[0], &priv1, sizeof(priv1)); - memcpy(&priv_param[4], &priv2, sizeof(priv2)); + SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); + SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); /* Emulate 64bit increment */ priv1++; @@ -125,8 +125,8 @@ snmpv3_build_priv_param(u8_t* priv_param) #else /* Based on RFC3414 */ static u32_t ctr; u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); - memcpy(&priv_param[0], &boots, 4); - memcpy(&priv_param[4], &ctr, 4); + SMEMCPY(&priv_param[0], &boots, 4); + SMEMCPY(&priv_param[4], &ctr, 4); ctr++; #endif return ERR_OK; diff --git a/src/apps/snmp/snmpv3_mbedtls.c b/src/apps/snmp/snmpv3_mbedtls.c index 2a0598ba..0b1eefb8 100644 --- a/src/apps/snmp/snmpv3_mbedtls.c +++ b/src/apps/snmp/snmpv3_mbedtls.c @@ -192,7 +192,7 @@ snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, iv_local[4 + 1] = (engine_time >> 16) & 0xFF; iv_local[4 + 2] = (engine_time >> 8) & 0xFF; iv_local[4 + 3] = (engine_time >> 0) & 0xFF; - memcpy(iv_local + 8, priv_param, 8); + SMEMCPY(iv_local + 8, priv_param, 8); if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { goto error; } @@ -263,9 +263,9 @@ snmpv3_password_to_key_md5( /* May want to ensure that engineLength <= 32, */ /* otherwise need to use a buffer larger than 64 */ /*****************************************************/ - memcpy(password_buf, key, 16); - memcpy(password_buf + 16, engineID, engineLength); - memcpy(password_buf + 16 + engineLength, key, 16); + SMEMCPY(password_buf, key, 16); + MEMCPY(password_buf + 16, engineID, engineLength); + SMEMCPY(password_buf + 16 + engineLength, key, 16); mbedtls_md5_starts(&MD); mbedtls_md5_update(&MD, password_buf, 32 + engineLength); @@ -316,9 +316,9 @@ snmpv3_password_to_key_sha( /* May want to ensure that engineLength <= 32, */ /* otherwise need to use a buffer larger than 72 */ /*****************************************************/ - memcpy(password_buf, key, 20); - memcpy(password_buf + 20, engineID, engineLength); - memcpy(password_buf + 20 + engineLength, key, 20); + SMEMCPY(password_buf, key, 20); + MEMCPY(password_buf + 20, engineID, engineLength); + SMEMCPY(password_buf + 20 + engineLength, key, 20); mbedtls_sha1_starts(&SH); mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); diff --git a/src/apps/sntp/sntp.c b/src/apps/sntp/sntp.c index 8d43eb0b..fb952111 100644 --- a/src/apps/sntp/sntp.c +++ b/src/apps/sntp/sntp.c @@ -212,13 +212,13 @@ sntp_process(u32_t *receive_timestamp) /* convert SNTP time (1900-based) to unix GMT time (1970-based) * if MSB is 0, SNTP time is 2036-based! */ - u32_t rx_secs = ntohl(receive_timestamp[0]); + u32_t rx_secs = lwip_ntohl(receive_timestamp[0]); int is_1900_based = ((rx_secs & 0x80000000) != 0); u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); time_t tim = t; #if SNTP_CALC_TIME_US - u32_t us = ntohl(receive_timestamp[1]) / 4295; + u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295; SNTP_SET_SYSTEM_TIME_US(t, us); /* display local time from GMT time */ LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); @@ -247,10 +247,10 @@ sntp_initialize_request(struct sntp_msg *req) u32_t sntp_time_sec, sntp_time_us; /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); - sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970); + sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970); req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; /* we send/save us instead of fraction to be faster... */ - sntp_last_timestamp_sent[1] = htonl(sntp_time_us); + sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us); req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; } #endif /* SNTP_CHECK_RESPONSE >= 2 */ @@ -688,7 +688,7 @@ sntp_getserver(u8_t idx) if (idx < SNTP_MAX_SERVERS) { return &sntp_servers[idx].addr; } - return IP_ADDR_ANY; + return IP4_ADDR_ANY; } #if SNTP_SERVER_DNS diff --git a/src/apps/tftp/tftp_server.c b/src/apps/tftp/tftp_server.c new file mode 100644 index 00000000..243b0924 --- /dev/null +++ b/src/apps/tftp/tftp_server.c @@ -0,0 +1,417 @@ +/****************************************************************//** + * + * @file tftp_server.c + * + * @author Logan Gunthorpe + * Dirk Ziegelmeier + * + * @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 + * Dirk Ziegelmeier + * + */ + +/** + * @defgroup tftp TFTP server + * @ingroup apps + * + * This is simple TFTP server for the lwIP raw API. + */ + +#include "lwip/apps/tftp_server.h" + +#if LWIP_UDP + +#include "lwip/udp.h" +#include "lwip/timeouts.h" +#include "lwip/debug.h" + +#define TFTP_MAX_PAYLOAD_SIZE 512 +#define TFTP_HEADER_LENGTH 4 + +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 + +enum tftp_error { + TFTP_ERROR_FILE_NOT_FOUND = 1, + TFTP_ERROR_ACCESS_VIOLATION = 2, + TFTP_ERROR_DISK_FULL = 3, + TFTP_ERROR_ILLEGAL_OPERATION = 4, + TFTP_ERROR_UNKNOWN_TRFR_ID = 5, + TFTP_ERROR_FILE_EXISTS = 6, + TFTP_ERROR_NO_SUCH_USER = 7 +}; + +#include + +struct tftp_state { + const struct tftp_context *ctx; + void *handle; + struct pbuf *last_data; + struct udp_pcb *upcb; + ip_addr_t addr; + u16_t port; + int timer; + int last_pkt; + u16_t blknum; + u8_t retries; + u8_t mode_write; +}; + +static struct tftp_state tftp_state; + +static void tftp_tmr(void* arg); + +static void +close_handle(void) +{ + tftp_state.port = 0; + ip_addr_set_any(0, &tftp_state.addr); + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + tftp_state.last_data = NULL; + } + + sys_untimeout(tftp_tmr, NULL); + + if (tftp_state.handle) { + tftp_state.ctx->close(tftp_state.handle); + tftp_state.handle = NULL; + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); + } +} + +static void +send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) +{ + int str_length = strlen(str); + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); + if(p == NULL) { + return; + } + + payload = (u16_t*) p->payload; + payload[0] = PP_HTONS(TFTP_ERROR); + payload[1] = lwip_htons(code); + MEMCPY(&payload[2], str, str_length + 1); + + udp_sendto(tftp_state.upcb, p, addr, port); + pbuf_free(p); +} + +static void +send_ack(u16_t blknum) +{ + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); + if(p == NULL) { + return; + } + payload = (u16_t*) p->payload; + + payload[0] = PP_HTONS(TFTP_ACK); + payload[1] = lwip_htons(blknum); + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +resend_data(void) +{ + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); + if(p == NULL) { + return; + } + + if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { + pbuf_free(p); + return; + } + + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +send_data(void) +{ + u16_t *payload; + int ret; + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + } + + tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); + if(tftp_state.last_data == NULL) { + return; + } + + payload = (u16_t *) tftp_state.last_data->payload; + payload[0] = PP_HTONS(TFTP_DATA); + payload[1] = lwip_htons(tftp_state.blknum); + + ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); + if (ret < 0) { + send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); + close_handle(); + return; + } + + pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); + resend_data(); +} + +static void +recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u16_t *sbuf = (u16_t *) p->payload; + int opcode; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(upcb); + + if (((tftp_state.port != 0) && (port != tftp_state.port)) || + (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + pbuf_free(p); + return; + } + + opcode = sbuf[0]; + + tftp_state.last_pkt = tftp_state.timer; + tftp_state.retries = 0; + + switch (opcode) { + case PP_HTONS(TFTP_RRQ): /* fall through */ + case PP_HTONS(TFTP_WRQ): + { + const char tftp_null = 0; + char filename[TFTP_MAX_FILENAME_LEN]; + char mode[TFTP_MAX_MODE_LEN]; + u16_t filename_end_offset; + u16_t mode_end_offset; + + if(tftp_state.handle != NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + break; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + /* find \0 in pbuf -> end of filename string */ + filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); + if((u16_t)(filename_end_offset-2) > sizeof(filename)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, filename, filename_end_offset-2, 2); + + /* find \0 in pbuf -> end of mode string */ + mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); + if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); + + tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); + tftp_state.blknum = 1; + + if (!tftp_state.handle) { + send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); + break; + } + + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); + ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); + + ip_addr_copy(tftp_state.addr, *addr); + tftp_state.port = port; + + if (opcode == PP_HTONS(TFTP_WRQ)) { + tftp_state.mode_write = 1; + send_ack(0); + } else { + tftp_state.mode_write = 0; + send_data(); + } + + break; + } + + case PP_HTONS(TFTP_DATA): + { + int ret; + u16_t blknum; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 1) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + pbuf_header(p, -TFTP_HEADER_LENGTH); + + ret = tftp_state.ctx->write(tftp_state.handle, p); + if (ret < 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); + close_handle(); + } else { + send_ack(blknum); + } + + if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { + close_handle(); + } + break; + } + + case PP_HTONS(TFTP_ACK): + { + u16_t blknum; + int lastpkt; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + if (blknum != tftp_state.blknum) { + send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); + break; + } + + lastpkt = 0; + + if (tftp_state.last_data != NULL) { + lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); + } + + if (!lastpkt) { + tftp_state.blknum++; + send_data(); + } else { + close_handle(); + } + + break; + } + + default: + send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); + break; + } + + pbuf_free(p); +} + +static void +tftp_tmr(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + tftp_state.timer++; + + if (tftp_state.handle == NULL) { + return; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { + if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); + resend_data(); + tftp_state.retries++; + } else { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); + close_handle(); + } + } +} + +/** @ingroup tftp + * Initialize TFTP server. + * @param ctx TFTP callback struct + */ +err_t +tftp_init(const struct tftp_context *ctx) +{ + err_t ret; + + struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (pcb == NULL) { + return ERR_MEM; + } + + ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); + if (ret != ERR_OK) { + udp_remove(pcb); + return ret; + } + + tftp_state.handle = NULL; + tftp_state.port = 0; + tftp_state.ctx = ctx; + tftp_state.timer = 0; + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + + udp_recv(pcb, recv, NULL); + + return ERR_OK; +} + +#endif /* LWIP_UDP */ diff --git a/src/core/def.c b/src/core/def.c index bb4b8e01..99f3d62e 100644 --- a/src/core/def.c +++ b/src/core/def.c @@ -2,6 +2,24 @@ * @file * Common functions used throughout the stack. * + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * \#define lwip_htons(x) your_htons + * \#define lwip_htonl(x) your_htonl + * + * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts. + * + * If you \#define them to htons() and htonl(), you should + * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from + * defining htonx/ntohx compatibility macros. + + * @defgroup sys_nonstandard Non-standard functions + * @ingroup sys_layer + * lwIP provides default implementations for non-standard functions. + * These can be mapped to OS functions to reduce code footprint if desired. */ /* @@ -39,21 +57,11 @@ #include "lwip/opt.h" #include "lwip/def.h" -/** - * These are reference implementations of the byte swapping functions. - * Again with the aim of being simple, correct and fully portable. - * Byte swapping is the second thing you would want to optimize. You will - * need to port it to your architecture and in your cc.h: - * - * #define LWIP_PLATFORM_BYTESWAP 1 - * #define LWIP_PLATFORM_HTONS(x) - * #define LWIP_PLATFORM_HTONL(x) - * - * Note ntohs() and ntohl() are merely references to the htonx counterparts. - */ +#include -#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) +#if BYTE_ORDER == LITTLE_ENDIAN +#if !defined(lwip_htons) /** * Convert an u16_t from host- to network byte order. * @@ -63,21 +71,11 @@ u16_t lwip_htons(u16_t n) { - return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); -} - -/** - * Convert an u16_t from network- to host byte order. - * - * @param n u16_t in network byte order - * @return n in host byte order - */ -u16_t -lwip_ntohs(u16_t n) -{ - return lwip_htons(n); + return (u16_t)PP_HTONS(n); } +#endif /* lwip_htons */ +#if !defined(lwip_htonl) /** * Convert an u32_t from host- to network byte order. * @@ -87,22 +85,134 @@ lwip_ntohs(u16_t n) u32_t lwip_htonl(u32_t n) { - return ((n & 0xff) << 24) | - ((n & 0xff00) << 8) | - ((n & 0xff0000UL) >> 8) | - ((n & 0xff000000UL) >> 24); + return (u32_t)PP_HTONL(n); } +#endif /* lwip_htonl */ +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#ifndef lwip_strnstr /** - * Convert an u32_t from network- to host byte order. - * - * @param n u32_t in network byte order - * @return n in host byte order + * @ingroup sys_nonstandard + * lwIP default implementation for strnstr() non-standard function. + * This can be \#defined to strnstr() depending on your platform port. */ -u32_t -lwip_ntohl(u32_t n) +char* +lwip_strnstr(const char* buffer, const char* token, size_t n) { - return lwip_htonl(n); + const char* p; + int tokenlen = (int)strlen(token); + if (tokenlen == 0) { + return (char *)(size_t)buffer; + } + for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { + if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { + return (char *)(size_t)p; + } + } + return NULL; } +#endif -#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ +#ifndef lwip_stricmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for stricmp() non-standard function. + * This can be \#defined to stricmp() depending on your platform port. + */ +int +lwip_stricmp(const char* str1, const char* str2) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (c1 != 0); + return 0; +} +#endif + +#ifndef lwip_strnicmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnicmp() non-standard function. + * This can be \#defined to strnicmp() depending on your platform port. + */ +int +lwip_strnicmp(const char* str1, const char* str2, size_t len) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (len-- && c1 != 0); + return 0; +} +#endif + +#ifndef lwip_itoa +/** + * @ingroup sys_nonstandard + * lwIP default implementation for itoa() non-standard function. + * This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port. + */ +void +lwip_itoa(char* result, size_t bufsize, int number) +{ + const int base = 10; + char* ptr = result, *ptr1 = result, tmp_char; + int tmp_value; + LWIP_UNUSED_ARG(bufsize); + + do { + tmp_value = number; + number /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)]; + } while(number); + + /* Apply negative sign */ + if (tmp_value < 0) { + *ptr++ = '-'; + } + *ptr-- = '\0'; + while(ptr1 < ptr) { + tmp_char = *ptr; + *ptr--= *ptr1; + *ptr1++ = tmp_char; + } +} +#endif diff --git a/src/core/dns.c b/src/core/dns.c index 9aed4733..2aa1dd99 100644 --- a/src/core/dns.c +++ b/src/core/dns.c @@ -1,6 +1,32 @@ /** * @file * DNS - host name to IP address resolver. + * + * @defgroup dns DNS + * @ingroup callbackstyle_api + * + * Implements a DNS host name to IP address resolver. + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + * + * All functions must be called from TCPIP thread. + * + * @see @ref netconn_common for thread-safe access. */ /* @@ -37,34 +63,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * @defgroup dns DNS - * @ingroup callbackstyle_api - * - * Implements a DNS host name to IP address resolver. - * - * The lwIP DNS resolver functions are used to lookup a host name and - * map it to a numerical IP address. It maintains a list of resolved - * hostnames that can be queried with the dns_lookup() function. - * New hostnames can be resolved using the dns_query() function. - * - * The lwIP version of the resolver also adds a non-blocking version of - * gethostbyname() that will work with a raw API application. This function - * checks for an IP address string first and converts it if it is valid. - * gethostbyname() then does a dns_lookup() to see if the name is - * already in the table. If so, the IP is returned. If not, a query is - * issued and the function returns with a ERR_INPROGRESS status. The app - * using the dns client must then go into a waiting state. - * - * Once a hostname has been resolved (or found to be non-existent), - * the resolver code calls a specified callback function (which - * must be implemented by the module that uses the resolver). - * - * All functions must be called from TCPIP thread. - * - * @see @ref netconn_common for thread-safe access. - */ - /*----------------------------------------------------------------------------- * RFC 1035 - Domain names - implementation and specification * RFC 2181 - Clarifications to the DNS Specification @@ -82,10 +80,12 @@ #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ +#include "lwip/def.h" #include "lwip/udp.h" #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/dns.h" +#include "lwip/prot/dns.h" #include @@ -104,11 +104,6 @@ static u16_t dns_txid; #define DNS_PORT_ALLOWED(port) ((port) >= 1024) #endif -/** DNS server port address */ -#ifndef DNS_SERVER_PORT -#define DNS_SERVER_PORT 53 -#endif - /** DNS maximum number of retries when asking for a name, before "timeout". */ #ifndef DNS_MAX_RETRIES #define DNS_MAX_RETRIES 4 @@ -165,71 +160,6 @@ static u16_t dns_txid; #define LWIP_DNS_SET_ADDRTYPE(x, y) #endif /* LWIP_IPV4 && LWIP_IPV6 */ -/** DNS field TYPE used for "Resource Records" */ -#define DNS_RRTYPE_A 1 /* a host address */ -#define DNS_RRTYPE_NS 2 /* an authoritative name server */ -#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ -#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ -#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ -#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ -#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ -#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ -#define DNS_RRTYPE_WKS 11 /* a well known service description */ -#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ -#define DNS_RRTYPE_HINFO 13 /* host information */ -#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ -#define DNS_RRTYPE_MX 15 /* mail exchange */ -#define DNS_RRTYPE_TXT 16 /* text strings */ -#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ - -/** DNS field CLASS used for "Resource Records" */ -#define DNS_RRCLASS_IN 1 /* the Internet */ -#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ -#define DNS_RRCLASS_CH 3 /* the CHAOS class */ -#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ -#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ - -/* DNS protocol flags */ -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 - -/* DNS protocol states */ -#define DNS_STATE_UNUSED 0 -#define DNS_STATE_NEW 1 -#define DNS_STATE_ASKING 2 -#define DNS_STATE_DONE 3 - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** DNS message header */ -struct dns_hdr { - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FLD_8(u8_t flags1); - PACK_STRUCT_FLD_8(u8_t flags2); - PACK_STRUCT_FIELD(u16_t numquestions); - PACK_STRUCT_FIELD(u16_t numanswers); - PACK_STRUCT_FIELD(u16_t numauthrr); - PACK_STRUCT_FIELD(u16_t numextrarr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define SIZEOF_DNS_HDR 12 - /** DNS query message structure. No packing needed: only used locally on the stack. */ struct dns_query { @@ -254,6 +184,14 @@ struct dns_answer { /* maximum allowed size for the struct due to non-packed */ #define SIZEOF_DNS_ANSWER_ASSERT 12 +/* DNS table entry states */ +typedef enum { + DNS_STATE_UNUSED = 0, + DNS_STATE_NEW = 1, + DNS_STATE_ASKING = 2, + DNS_STATE_DONE = 3 +} dns_state_enum_t; + /** DNS table entry */ struct dns_table_entry { u32_t ttl; @@ -334,40 +272,6 @@ static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; static ip_addr_t dns_servers[DNS_MAX_SERVERS]; -#ifndef LWIP_DNS_STRICMP -#define LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2) -/** - * A small but sufficient implementation for case insensitive strcmp. - * This can be defined to e.g. stricmp for windows or strcasecmp for linux. */ -static int -dns_stricmp(const char* str1, const char* str2) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (c1 != 0); - return 0; -} -#endif /* LWIP_DNS_STRICMP */ - /** * Initialize the resolver: set up the UDP pcb and configure the default server * (if DNS_SERVER_ADDRESS is set). @@ -425,7 +329,7 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) if (dnsserver != NULL) { dns_servers[numdns] = (*dnsserver); } else { - dns_servers[numdns] = *IP_ADDR_ANY; + dns_servers[numdns] = *IP4_ADDR_ANY; } } } @@ -444,7 +348,7 @@ dns_getserver(u8_t numdns) if (numdns < DNS_MAX_SERVERS) { return &dns_servers[numdns]; } else { - return IP_ADDR_ANY; + return IP4_ADDR_ANY; } } @@ -504,7 +408,7 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_ #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC struct local_hostlist_entry *entry = local_hostlist_dynamic; while (entry != NULL) { - if ((LWIP_DNS_STRICMP(entry->name, hostname) == 0) && + if ((lwip_stricmp(entry->name, hostname) == 0) && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { if (addr) { ip_addr_copy(*addr, entry->addr); @@ -516,7 +420,7 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_ #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ size_t i; for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if ((LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) && + if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { if (addr) { ip_addr_copy(*addr, local_hostlist_static[i].addr); @@ -546,7 +450,7 @@ dns_local_removehost(const char *hostname, const ip_addr_t *addr) struct local_hostlist_entry *entry = local_hostlist_dynamic; struct local_hostlist_entry *last_entry = NULL; while (entry != NULL) { - if (((hostname == NULL) || !LWIP_DNS_STRICMP(entry->name, hostname)) && + if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) && ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { struct local_hostlist_entry *free_entry; if (last_entry != NULL) { @@ -635,7 +539,7 @@ dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addr /* Walk through name list, return entry if found. If not, return NULL. */ for (i = 0; i < DNS_TABLE_SIZE; ++i) { if ((dns_table[i].state == DNS_STATE_DONE) && - (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0) && + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) && LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); @@ -664,11 +568,14 @@ dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addr static u16_t dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) { - unsigned char n; + int n; u16_t response_offset = start_offset; do { - n = pbuf_get_at(p, response_offset++); + n = pbuf_try_get_at(p, response_offset++); + if (n < 0) { + return 0xFFFF; + } /** @see RFC 1035 - 4.1.4. Message compression */ if ((n & 0xc0) == 0xc0) { /* Compressed name: cannot be equal since we don't send them */ @@ -676,7 +583,11 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) } else { /* Not compressed name */ while (n > 0) { - if ((*query) != pbuf_get_at(p, response_offset)) { + int c = pbuf_try_get_at(p, response_offset); + if (c < 0) { + return 0xFFFF; + } + if ((*query) != (u8_t)c) { return 0xFFFF; } ++response_offset; @@ -685,7 +596,11 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) } ++query; } - } while (pbuf_get_at(p, response_offset) != 0); + n = pbuf_try_get_at(p, response_offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); return response_offset + 1; } @@ -698,26 +613,34 @@ dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) * @return index to end of the name */ static u16_t -dns_parse_name(struct pbuf* p, u16_t query_idx) +dns_skip_name(struct pbuf* p, u16_t query_idx) { - unsigned char n; + int n; + u16_t offset = query_idx; do { - n = pbuf_get_at(p, query_idx++); + n = pbuf_try_get_at(p, offset++); + if (n < 0) { + return 0xFFFF; + } /** @see RFC 1035 - 4.1.4. Message compression */ if ((n & 0xc0) == 0xc0) { - /* Compressed name */ + /* Compressed name: since we only want to skip it (not check it), stop here */ break; } else { /* Not compressed name */ - while (n > 0) { - ++query_idx; - --n; + if (offset + n >= p->tot_len) { + return 0xFFFF; } + offset = (u16_t)(offset + n); } - } while (pbuf_get_at(p, query_idx) != 0); + n = pbuf_try_get_at(p, offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); - return query_idx + 1; + return offset + 1; } /** @@ -757,7 +680,7 @@ dns_send(u8_t idx) if (p != NULL) { /* fill dns header */ memset(&hdr, 0, SIZEOF_DNS_HDR); - hdr.id = htons(entry->txid); + hdr.id = lwip_htons(entry->txid); hdr.flags1 = DNS_FLAG1_RD; hdr.numquestions = PP_HTONS(1); pbuf_take(p, &hdr, SIZEOF_DNS_HDR); @@ -982,12 +905,9 @@ dns_check_entry(u8_t i) LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); switch (entry->state) { - - case DNS_STATE_NEW: { - u16_t txid; + case DNS_STATE_NEW: /* initialize new entry */ - txid = dns_create_txid(); - entry->txid = txid; + entry->txid = dns_create_txid(); entry->state = DNS_STATE_ASKING; entry->server_idx = 0; entry->tmr = 1; @@ -1000,8 +920,6 @@ dns_check_entry(u8_t i) ("dns_send returned error: %s\n", lwip_strerr(err))); } break; - } - case DNS_STATE_ASKING: if (--entry->tmr == 0) { if (++entry->retries == DNS_MAX_RETRIES) { @@ -1095,8 +1013,6 @@ dns_correct_response(u8_t idx, u32_t ttl) } /** * Receive input function for DNS response packets arriving for the dns UDP pcb. - * - * @params see udp.h */ static void dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) @@ -1123,7 +1039,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, /* copy dns payload inside static buffer for processing */ if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { /* Match the ID in the DNS header with the name table. */ - txid = htons(hdr.id); + txid = lwip_htons(hdr.id); for (i = 0; i < DNS_TABLE_SIZE; i++) { const struct dns_table_entry *entry = &dns_table[i]; if ((entry->state == DNS_STATE_ASKING) && @@ -1131,8 +1047,8 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, /* We only care about the question(s) and the answers. The authrr and the extrarr are simply discarded. */ - nquestions = htons(hdr.numquestions); - nanswers = htons(hdr.numanswers); + nquestions = lwip_htons(hdr.numquestions); + nanswers = lwip_htons(hdr.numanswers); /* Check for correct response. */ if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) { @@ -1159,7 +1075,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, } /* check if "question" part matches the request */ - pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx); + if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) { + goto memerr; /* ignore this packet */ + } if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { @@ -1175,11 +1093,17 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, } else { while ((nanswers > 0) && (res_idx < p->tot_len)) { /* skip answer resource record's host name */ - res_idx = dns_parse_name(p, res_idx); + res_idx = dns_skip_name(p, res_idx); + if (res_idx == 0xFFFF) { + goto memerr; /* ignore this packet */ + } /* Check for IP address type and Internet class. Others are discarded. */ - pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx); + if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) { + goto memerr; /* ignore this packet */ + } res_idx += SIZEOF_DNS_ANSWER; + if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { #if LWIP_IPV4 if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { @@ -1189,11 +1113,13 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, { ip4_addr_t ip4addr; /* read the IP address after answer resource record's header */ - pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx); + if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) { + goto memerr; /* ignore this packet */ + } ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); pbuf_free(p); /* handle correct response */ - dns_correct_response(i, ntohl(ans.ttl)); + dns_correct_response(i, lwip_ntohl(ans.ttl)); return; } } @@ -1206,18 +1132,23 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, { ip6_addr_t ip6addr; /* read the IP address after answer resource record's header */ - pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx); + if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) { + goto memerr; /* ignore this packet */ + } ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); pbuf_free(p); /* handle correct response */ - dns_correct_response(i, ntohl(ans.ttl)); + dns_correct_response(i, lwip_ntohl(ans.ttl)); return; } } #endif /* LWIP_IPV6 */ } /* skip this answer */ - res_idx += htons(ans.len); + if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) { + goto memerr; /* ignore this packet */ + } + res_idx += lwip_htons(ans.len); --nanswers; } #if LWIP_IPV4 && LWIP_IPV6 @@ -1260,7 +1191,7 @@ memerr: * @param hostnamelen length of the hostname * @param found a callback function to be called on success, failure or timeout * @param callback_arg argument to pass to the callback function - * @return @return a err_t return code. + * @return err_t return code. */ static err_t dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, @@ -1277,7 +1208,7 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, /* check for duplicate entries */ for (i = 0; i < DNS_TABLE_SIZE; i++) { if ((dns_table[i].state == DNS_STATE_ASKING) && - (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) { + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) { #if LWIP_IPV4 && LWIP_IPV6 if (dns_table[i].reqaddrtype != dns_addrtype) { /* requested address types don't match @@ -1424,7 +1355,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun * @param found a callback function to be called on success, failure or timeout (only if * ERR_INPROGRESS is returned!) * @param callback_arg argument to pass to the callback function - * @param dns_addrtype: - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only + * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only diff --git a/src/core/inet_chksum.c b/src/core/inet_chksum.c index 57cbad79..80289528 100644 --- a/src/core/inet_chksum.c +++ b/src/core/inet_chksum.c @@ -1,7 +1,16 @@ /** * @file - * Incluse internet checksum functions. + * Incluse internet checksum functions.\n * + * These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * \#define LWIP_CHKSUM your_checksum_routine + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. */ /* @@ -45,17 +54,6 @@ #include #include -/* These are some reference implementations of the checksum algorithm, with the - * aim of being simple, correct and fully portable. Checksumming is the - * first thing you would want to optimize for your platform. If you create - * your own version, link it in and in your cc.h put: - * - * #define LWIP_CHKSUM - * - * Or you can select from the implementations below by defining - * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. - */ - #ifndef LWIP_CHKSUM # define LWIP_CHKSUM lwip_standard_chksum # ifndef LWIP_CHKSUM_ALGORITHM @@ -110,10 +108,10 @@ lwip_standard_chksum(const void *dataptr, int len) if ((acc & 0xffff0000UL) != 0) { acc = (acc >> 16) + (acc & 0x0000ffffUL); } - /* This maybe a little confusing: reorder sum using htons() - instead of ntohs() since it has a little less call overhead. + /* This maybe a little confusing: reorder sum using lwip_htons() + instead of lwip_ntohs() since it has a little less call overhead. The caller must invert bits for Internet sum ! */ - return htons((u16_t)acc); + return lwip_htons((u16_t)acc); } #endif @@ -285,8 +283,8 @@ inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) acc = SWAP_BYTES_IN_WORD(acc); } - acc += (u32_t)htons((u16_t)proto); - acc += (u32_t)htons(proto_len); + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); /* Fold 32-bit sum to 16 bits calling this twice is probably faster than if statements... */ @@ -431,8 +429,8 @@ inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, acc = SWAP_BYTES_IN_WORD(acc); } - acc += (u32_t)htons((u16_t)proto); - acc += (u32_t)htons(proto_len); + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); /* Fold 32-bit sum to 16 bits calling this twice is probably faster than if statements... */ diff --git a/src/core/init.c b/src/core/init.c index 092cd2bc..0eb1e44c 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -35,27 +35,6 @@ * Author: Adam Dunkels */ -/** - * @defgroup lwip_nosys Mainloop mode ("NO_SYS") - * @ingroup lwip - * Use this mode if you do not run an OS on your system. \#define NO_SYS to 1. - * Feed incoming packets to netif->input(pbuf, netif) function from mainloop, - * *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt - * context and put them into a queue which is processed from mainloop.\n - * Call sys_check_timeouts() periodically in the mainloop.\n - * Porting: implement all functions in @ref sys_time and @ref sys_prot.\n - * You can only use @ref callbackstyle_api in this mode. - * - * @defgroup lwip_os OS mode (TCPIP thread) - * @ingroup lwip - * Use this mode if you run an OS on your system. It is recommended to - * use an RTOS that correctly handles priority inversion and - * to use LWIP_TCPIP_CORE_LOCKING.\n - * Porting: implement all functions in @ref sys_layer.\n - * You can use @ref callbackstyle_api together with \#define tcpip_callback, - * and all @ref threadsafe_api. - */ - #include "lwip/opt.h" #include "lwip/init.h" @@ -70,7 +49,6 @@ #include "lwip/raw.h" #include "lwip/udp.h" #include "lwip/priv/tcp_priv.h" -#include "lwip/autoip.h" #include "lwip/igmp.h" #include "lwip/dns.h" #include "lwip/timeouts.h" @@ -83,6 +61,25 @@ #include "netif/ppp/ppp_opts.h" #include "netif/ppp/ppp_impl.h" +#ifndef LWIP_SKIP_PACKING_CHECK + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct packed_struct_test +{ + PACK_STRUCT_FLD_8(u8_t dummy1); + PACK_STRUCT_FIELD(u32_t dummy2); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5 + +#endif + /* Compile-time sanity checks for configuration errors. * These can be done independently of LWIP_DEBUG, without penalty. */ @@ -222,7 +219,7 @@ #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" #endif #if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) - #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" + #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)" #endif #if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" @@ -230,9 +227,6 @@ #if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" #endif -#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF - #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" -#endif #if LWIP_NETCONN && LWIP_TCP #if NETCONN_COPY != TCP_WRITE_FLAG_COPY #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" @@ -325,10 +319,10 @@ #if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #endif -#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #endif -#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." #endif #if TCP_WND < TCP_MSS @@ -345,6 +339,10 @@ void lwip_init(void) { +#ifndef LWIP_SKIP_PACKING_CHECK + LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); +#endif + /* Modules initialization */ stats_init(); #if !NO_SYS @@ -369,9 +367,6 @@ lwip_init(void) #if LWIP_TCP tcp_init(); #endif /* LWIP_TCP */ -#if LWIP_AUTOIP - autoip_init(); -#endif /* LWIP_AUTOIP */ #if LWIP_IGMP igmp_init(); #endif /* LWIP_IGMP */ diff --git a/src/core/ip.c b/src/core/ip.c index a1685e3a..2e024085 100644 --- a/src/core/ip.c +++ b/src/core/ip.c @@ -1,7 +1,24 @@ /** - * @file ip.c + * @file * Common IPv4 and IPv6 code * + * @defgroup ip IP + * @ingroup callbackstyle_api + * + * @defgroup ip4 IPv4 + * @ingroup ip + * + * @defgroup ip6 IPv6 + * @ingroup ip + * + * @defgroup ipaddr IP address handling + * @ingroup infrastructure + * + * @defgroup ip4addr IPv4 only + * @ingroup ipaddr + * + * @defgroup ip6addr IPv6 only + * @ingroup ipaddr */ /* @@ -36,23 +53,6 @@ * */ -/** - * @defgroup ip4 IPv4 - * @ingroup callbackstyle_api - * - * @defgroup ip6 IPv6 - * @ingroup callbackstyle_api - * - * @defgroup ipaddr IP address handling - * @ingroup infrastructure - * - * @defgroup ip4addr IPv4 only - * @ingroup ipaddr - * - * @defgroup ip6addr IPv6 only - * @ingroup ipaddr - */ - #include "lwip/opt.h" #if LWIP_IPV4 || LWIP_IPV6 diff --git a/src/core/ipv4/autoip.c b/src/core/ipv4/autoip.c index 8ca26712..86a4aed3 100644 --- a/src/core/ipv4/autoip.c +++ b/src/core/ipv4/autoip.c @@ -2,6 +2,28 @@ * @file * AutoIP Automatic LinkLocal IP Configuration * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * @defgroup autoip AUTOIP + * @ingroup ip4 + * AUTOIP related functions + * USAGE: + * + * define @ref LWIP_AUTOIP 1 in your lwipopts.h + * Options: + * AUTOIP_TMR_INTERVAL msecs, + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + * @see netifapi_autoip */ /* @@ -32,41 +54,6 @@ * OF SUCH DAMAGE. * * Author: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - * - * Please coordinate changes and requests with Dominik Spies - * - */ - -/******************************************************************************* - * USAGE: - * - * define LWIP_AUTOIP 1 in your lwipopts.h - * - * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): - * - First, call autoip_init(). - * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, - * that should be defined in autoip.h. - * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. - * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... - * - * Without DHCP: - * - Call autoip_start() after netif_add(). - * - * With DHCP: - * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. - * - Configure your DHCP Client. - * - */ - -/** - * @defgroup autoip AUTOIP - * @ingroup ip4 - * AUTOIP related functions - * @see netifapi_autoip */ #include "lwip/opt.h" @@ -79,35 +66,11 @@ #include "lwip/netif.h" #include "lwip/autoip.h" #include "lwip/etharp.h" +#include "lwip/prot/autoip.h" #include #include -/* 169.254.0.0 */ -#define AUTOIP_NET 0xA9FE0000 -/* 169.254.1.0 */ -#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) -/* 169.254.254.255 */ -#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) - -/* RFC 3927 Constants */ -#define PROBE_WAIT 1 /* second (initial random delay) */ -#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ -#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ -#define PROBE_NUM 3 /* (number of probe packets) */ -#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ -#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ -#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ -#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ -#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ -#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ - -/* AutoIP client states */ -#define AUTOIP_STATE_OFF 0 -#define AUTOIP_STATE_PROBING 1 -#define AUTOIP_STATE_ANNOUNCING 2 -#define AUTOIP_STATE_BOUND 3 - /** Pseudo random macro based on netif informations. * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ #ifndef LWIP_AUTOIP_RAND @@ -115,7 +78,7 @@ ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ - (netif->autoip?netif->autoip->tried_llipaddr:0)) + (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) #endif /* LWIP_AUTOIP_RAND */ /** @@ -124,7 +87,7 @@ */ #ifndef LWIP_AUTOIP_CREATE_SEED_ADDR #define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ - htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) #endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ @@ -132,6 +95,7 @@ static err_t autoip_arp_announce(struct netif *netif); static void autoip_start_probing(struct netif *netif); +#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP)) /** * @ingroup autoip @@ -146,12 +110,13 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip) { LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("autoip != NULL", autoip != NULL); - LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); + LWIP_ASSERT("netif already has a struct autoip set", + netif_autoip_data(netif) == NULL); /* clear data structure */ memset(autoip, 0, sizeof(struct autoip)); /* autoip->state = AUTOIP_STATE_OFF; */ - netif->autoip = autoip; + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); } /** Restart AutoIP client and check the next address (conflict detected) @@ -161,7 +126,8 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip) static void autoip_restart(struct netif *netif) { - netif->autoip->tried_llipaddr++; + struct autoip* autoip = netif_autoip_data(netif); + autoip->tried_llipaddr++; autoip_start(netif); } @@ -171,6 +137,8 @@ autoip_restart(struct netif *netif) static void autoip_handle_arp_conflict(struct netif *netif) { + struct autoip* autoip = netif_autoip_data(netif); + /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where a) means retreat on the first conflict and b) allows to keep an already configured address when having only one @@ -178,7 +146,7 @@ autoip_handle_arp_conflict(struct netif *netif) We use option b) since it helps to improve the chance that one of the two conflicting hosts may be able to retain its address. */ - if (netif->autoip->lastconflict > 0) { + if (autoip->lastconflict > 0) { /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); @@ -189,7 +157,7 @@ autoip_handle_arp_conflict(struct netif *netif) LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); autoip_arp_announce(netif); - netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; } } @@ -202,12 +170,14 @@ autoip_handle_arp_conflict(struct netif *netif) static void autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) { + struct autoip* autoip = netif_autoip_data(netif); + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * compliant to RFC 3927 Section 2.1 * We have 254 * 256 possibilities */ - u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); - addr += netif->autoip->tried_llipaddr; + u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += autoip->tried_llipaddr; addr = AUTOIP_NET | (addr & 0xffff); /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ @@ -219,11 +189,11 @@ autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) } LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && (addr <= AUTOIP_RANGE_END)); - ip4_addr_set_u32(ipaddr, htonl(addr)); + ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); } @@ -235,8 +205,9 @@ autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) static err_t autoip_arp_probe(struct netif *netif) { + struct autoip* autoip = netif_autoip_data(netif); /* this works because netif->ip_addr is ANY */ - return etharp_request(netif, &netif->autoip->llipaddr); + return etharp_request(netif, &autoip->llipaddr); } /** @@ -258,7 +229,7 @@ autoip_arp_announce(struct netif *netif) static err_t autoip_bind(struct netif *netif) { - struct autoip *autoip = netif->autoip; + struct autoip* autoip = netif_autoip_data(netif); ip4_addr_t sn_mask, gw_addr; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, @@ -285,7 +256,7 @@ autoip_bind(struct netif *netif) err_t autoip_start(struct netif *netif) { - struct autoip *autoip = netif->autoip; + struct autoip* autoip = netif_autoip_data(netif); err_t result = ERR_OK; LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); @@ -293,7 +264,7 @@ autoip_start(struct netif *netif) /* Set IP-Address, Netmask and Gateway to 0 to make sure that * ARP Packets are formed correctly */ - netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], @@ -310,7 +281,7 @@ autoip_start(struct netif *netif) } memset(autoip, 0, sizeof(struct autoip)); /* store this AutoIP client in the netif */ - netif->autoip = autoip; + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); } else { autoip->state = AUTOIP_STATE_OFF; @@ -329,14 +300,14 @@ autoip_start(struct netif *netif) static void autoip_start_probing(struct netif *netif) { - struct autoip *autoip = netif->autoip; + struct autoip* autoip = netif_autoip_data(netif); autoip->state = AUTOIP_STATE_PROBING; autoip->sent_num = 0; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); /* time to wait to first probe, this is randomly * chosen out of 0 to PROBE_WAIT seconds. @@ -363,7 +334,9 @@ autoip_start_probing(struct netif *netif) void autoip_network_changed(struct netif *netif) { - if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { autoip_start_probing(netif); } } @@ -377,10 +350,12 @@ autoip_network_changed(struct netif *netif) err_t autoip_stop(struct netif *netif) { - if (netif->autoip) { - netif->autoip->state = AUTOIP_STATE_OFF; + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip != NULL) { + autoip->state = AUTOIP_STATE_OFF; if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { - netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); } } return ERR_OK; @@ -395,45 +370,46 @@ autoip_tmr(void) struct netif *netif = netif_list; /* loop through netif's */ while (netif != NULL) { + struct autoip* autoip = netif_autoip_data(netif); /* only act on AutoIP configured interfaces */ - if (netif->autoip != NULL) { - if (netif->autoip->lastconflict > 0) { - netif->autoip->lastconflict--; + if (autoip != NULL) { + if (autoip->lastconflict > 0) { + autoip->lastconflict--; } LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", - (u16_t)(netif->autoip->state), netif->autoip->ttw)); + (u16_t)(autoip->state), autoip->ttw)); - if (netif->autoip->ttw > 0) { - netif->autoip->ttw--; + if (autoip->ttw > 0) { + autoip->ttw--; } - switch(netif->autoip->state) { + switch(autoip->state) { case AUTOIP_STATE_PROBING: - if (netif->autoip->ttw == 0) { - if (netif->autoip->sent_num >= PROBE_NUM) { + if (autoip->ttw == 0) { + if (autoip->sent_num >= PROBE_NUM) { /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ - netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + autoip->state = AUTOIP_STATE_ANNOUNCING; autoip_bind(netif); /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP which counts as an announcement */ - netif->autoip->sent_num = 1; - netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + autoip->sent_num = 1; + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); } else { autoip_arp_probe(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); - netif->autoip->sent_num++; - if (netif->autoip->sent_num == PROBE_NUM) { + autoip->sent_num++; + if (autoip->sent_num == PROBE_NUM) { /* calculate time to wait to for announce */ - netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; } else { /* calculate time to wait to next probe */ - netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); } @@ -442,20 +418,20 @@ autoip_tmr(void) break; case AUTOIP_STATE_ANNOUNCING: - if (netif->autoip->ttw == 0) { + if (autoip->ttw == 0) { autoip_arp_announce(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); - netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; - netif->autoip->sent_num++; + autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + autoip->sent_num++; - if (netif->autoip->sent_num >= ANNOUNCE_NUM) { - netif->autoip->state = AUTOIP_STATE_BOUND; - netif->autoip->sent_num = 0; - netif->autoip->ttw = 0; + if (autoip->sent_num >= ANNOUNCE_NUM) { + autoip->state = AUTOIP_STATE_BOUND; + autoip->sent_num = 0; + autoip->ttw = 0; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); } } break; @@ -471,7 +447,7 @@ autoip_tmr(void) } /** - * Handles every incoming ARP Packet, called by etharp_arp_input. + * Handles every incoming ARP Packet, called by etharp_input(). * * @param netif network interface to use for autoip processing * @param hdr Incoming ARP packet @@ -479,8 +455,10 @@ autoip_tmr(void) void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) { + struct autoip* autoip = netif_autoip_data(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); - if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { /* when ip.src == llipaddr && hw.src != netif->hwaddr * * when probing ip.dst == llipaddr && hw.src != netif->hwaddr @@ -496,15 +474,15 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) IPADDR2_COPY(&sipaddr, &hdr->sipaddr); IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - if (netif->autoip->state == AUTOIP_STATE_PROBING) { + if (autoip->state == AUTOIP_STATE_PROBING) { /* RFC 3927 Section 2.2.1: * from beginning to after ANNOUNCE_WAIT * seconds we have a conflict if * ip.src == llipaddr OR * ip.dst == llipaddr && hw.src != own hwaddr */ - if ((ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || - (ip4_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || + (ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, ("autoip_arp_reply(): Probe Conflict detected\n")); @@ -515,7 +493,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) * in any state we have a conflict if * ip.src == llipaddr && hw.src != own hwaddr */ - if (ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); @@ -534,13 +512,18 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) u8_t autoip_supplied_address(const struct netif *netif) { - if ((netif != NULL) && (netif->autoip != NULL)) { - if ((netif->autoip->state == AUTOIP_STATE_BOUND) || - (netif->autoip->state == AUTOIP_STATE_ANNOUNCING)) { - return 1; - } + if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { + struct autoip* autoip = netif_autoip_data(netif); + return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); } return 0; } +u8_t +autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) +{ + struct autoip* autoip = netif_autoip_data(netif); + return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); +} + #endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/src/core/ipv4/dhcp.c b/src/core/ipv4/dhcp.c index b3307dac..de5fc73b 100644 --- a/src/core/ipv4/dhcp.c +++ b/src/core/ipv4/dhcp.c @@ -2,6 +2,26 @@ * @file * Dynamic Host Configuration Protocol client * + * @defgroup dhcp4 DHCPv4 + * @ingroup ip4 + * DHCP (IPv4) related functions + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * @todo: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Options: + * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * dhcp_start() starts a DHCP client instance which + * configures the interface by obtaining an IP address lease and maintaining it. + * + * Use dhcp_release() to end the lease and use dhcp_stop() + * to remove the DHCP client. + * + * @see netifapi_dhcp4 */ /* @@ -38,38 +58,6 @@ * * Author: Leon Woestenberg * - * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform - * with RFC 2131 and RFC 2132. - * - * @todo: - * - Support for interfaces other than Ethernet (SLIP, PPP, ...) - * - * Please coordinate changes and requests with Leon Woestenberg - * - * - * Integration with your code: - * - * In lwip/dhcp.h - * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) - * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) - * - * Then have your application call dhcp_coarse_tmr() and - * dhcp_fine_tmr() on the defined intervals. - * - * dhcp_start(struct netif *netif); - * starts a DHCP client instance which configures the interface by - * obtaining an IP address lease and maintaining it. - * - * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) - * to remove the DHCP client. - * - */ - -/** - * @defgroup dhcp4 DHCPv4 - * @ingroup ip4 - * DHCP (IPv4) related functions - * @see netifapi_dhcp4 */ #include "lwip/opt.h" @@ -86,6 +74,7 @@ #include "lwip/autoip.h" #include "lwip/dns.h" #include "lwip/etharp.h" +#include "lwip/prot/dhcp.h" #include @@ -204,6 +193,8 @@ static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); /* always add the DHCP options trailer to end and pad */ static void dhcp_option_trailer(struct dhcp *dhcp); +#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) + /** Ensure DHCP PCB is allocated and bound */ static err_t dhcp_inc_pcb_refcount(void) @@ -221,13 +212,13 @@ dhcp_inc_pcb_refcount(void) ip_set_option(dhcp_pcb, SOF_BROADCAST); /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ - udp_bind(dhcp_pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); - udp_connect(dhcp_pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); - udp_recv(dhcp_pcb, dhcp_recv, NULL); + udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT); + udp_recv(dhcp_pcb, dhcp_recv, NULL); } dhcp_pcb_refcount++; - + return ERR_OK; } @@ -237,7 +228,7 @@ dhcp_dec_pcb_refcount(void) { LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); dhcp_pcb_refcount--; - + if (dhcp_pcb_refcount == 0) { udp_remove(dhcp_pcb); dhcp_pcb = NULL; @@ -259,14 +250,15 @@ dhcp_dec_pcb_refcount(void) static void dhcp_handle_nak(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); /* Change to a defined state - set this before assigning the address to ensure the callback can use dhcp_supplied_address() */ dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); /* remove IP address from interface (must no longer be used, as per RFC2131) */ - netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); /* We can immediately restart discovery */ dhcp_discover(netif); } @@ -284,7 +276,7 @@ dhcp_handle_nak(struct netif *netif) static void dhcp_check(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; u16_t msecs; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], @@ -313,12 +305,13 @@ dhcp_check(struct netif *netif) static void dhcp_handle_offer(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); /* obtain the server address */ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { - ip_addr_set_ip4_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); /* remember offered address */ @@ -344,7 +337,7 @@ dhcp_handle_offer(struct netif *netif) static err_t dhcp_select(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; u16_t msecs; u8_t i; @@ -360,10 +353,10 @@ dhcp_select(struct netif *netif) /* MUST request the offered IP address */ dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { @@ -379,7 +372,7 @@ dhcp_select(struct netif *netif) pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); /* send broadcast to any DHCP server */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); } else { @@ -396,6 +389,7 @@ dhcp_select(struct netif *netif) /** * The DHCP timer that checks for lease renewal/rebind timeouts. + * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS). */ void dhcp_coarse_tmr(void) @@ -405,7 +399,7 @@ dhcp_coarse_tmr(void) /* iterate through all network interfaces */ while (netif != NULL) { /* only act on DHCP configured interfaces */ - struct dhcp* dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { /* compare lease time to expire timeout */ if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { @@ -431,7 +425,8 @@ dhcp_coarse_tmr(void) } /** - * DHCP transaction timeout handling + * DHCP transaction timeout handling (this function must be called every 500ms, + * see @ref DHCP_FINE_TIMER_MSECS). * * A DHCP server is expected to respond within a short period of time. * This timer checks whether an outstanding DHCP request is timed out. @@ -442,14 +437,15 @@ dhcp_fine_tmr(void) struct netif *netif = netif_list; /* loop through netif's */ while (netif != NULL) { + struct dhcp *dhcp = netif_dhcp_data(netif); /* only act on DHCP configured interfaces */ - if (netif->dhcp != NULL) { + if (dhcp != NULL) { /* timer is active (non zero), and is about to trigger now */ - if (netif->dhcp->request_timeout > 1) { - netif->dhcp->request_timeout--; + if (dhcp->request_timeout > 1) { + dhcp->request_timeout--; } - else if (netif->dhcp->request_timeout == 1) { - netif->dhcp->request_timeout--; + else if (dhcp->request_timeout == 1) { + dhcp->request_timeout--; /* { netif->dhcp->request_timeout == 0 } */ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); /* this client's request timeout triggered */ @@ -472,7 +468,8 @@ dhcp_fine_tmr(void) static void dhcp_timeout(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); /* back-off period has passed, or server selection timed out */ if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { @@ -518,7 +515,8 @@ dhcp_timeout(struct netif *netif) static void dhcp_t1_timeout(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING)) { @@ -530,9 +528,9 @@ dhcp_t1_timeout(struct netif *netif) DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ dhcp_renew(netif); /* Calculate next timeout */ - if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) { - netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2); + dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2); } } } @@ -545,7 +543,8 @@ dhcp_t1_timeout(struct netif *netif) static void dhcp_t2_timeout(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { @@ -556,9 +555,9 @@ dhcp_t2_timeout(struct netif *netif) DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ dhcp_rebind(netif); /* Calculate next timeout */ - if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) { - netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2); + dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2); } } } @@ -571,7 +570,8 @@ dhcp_t2_timeout(struct netif *netif) static void dhcp_handle_ack(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + #if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV u8_t n; #endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */ @@ -615,13 +615,13 @@ dhcp_handle_ack(struct netif *netif) #if LWIP_DHCP_BOOTP_FILE /* copy boot server address, boot file name copied in dhcp_parse_reply if not overloaded */ - ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); + ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); #endif /* LWIP_DHCP_BOOTP_FILE */ /* subnet mask given? */ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { /* remember given subnet mask */ - ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); dhcp->subnet_mask_given = 1; } else { dhcp->subnet_mask_given = 0; @@ -629,13 +629,13 @@ dhcp_handle_ack(struct netif *netif) /* gateway router */ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { - ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); } #if LWIP_DHCP_GET_NTP_SRV /* NTP servers */ for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { - ip4_addr_set_u32(&ntp_server_addrs[n], htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); + ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); } dhcp_set_ntp_servers(n, ntp_server_addrs); #endif /* LWIP_DHCP_GET_NTP_SRV */ @@ -644,7 +644,7 @@ dhcp_handle_ack(struct netif *netif) /* DNS servers */ for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { ip_addr_t dns_addr; - ip_addr_set_ip4_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); dns_setserver(n, &dns_addr); } #endif /* LWIP_DNS */ @@ -663,12 +663,12 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) { LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("dhcp != NULL", dhcp != NULL); - LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL); /* clear data structure */ memset(dhcp, 0, sizeof(struct dhcp)); /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - netif->dhcp = dhcp; + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); } /** @@ -684,9 +684,9 @@ void dhcp_cleanup(struct netif *netif) { LWIP_ASSERT("netif != NULL", netif != NULL); - if (netif->dhcp != NULL) { - mem_free(netif->dhcp); - netif->dhcp = NULL; + if (netif_dhcp_data(netif) != NULL) { + mem_free(netif_dhcp_data(netif)); + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); } } @@ -711,7 +711,7 @@ dhcp_start(struct netif *netif) LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); - dhcp = netif->dhcp; + dhcp = netif_dhcp_data(netif); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); /* check MTU of the netif */ @@ -728,9 +728,9 @@ dhcp_start(struct netif *netif) LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); return ERR_MEM; } - + /* store this dhcp client in the netif */ - netif->dhcp = dhcp; + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); /* already has DHCP client attached */ } else { @@ -748,7 +748,7 @@ dhcp_start(struct netif *netif) memset(dhcp, 0, sizeof(struct dhcp)); /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ return ERR_MEM; @@ -810,7 +810,7 @@ dhcp_inform(struct netif *netif) pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); - + udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); dhcp_delete_msg(&dhcp); @@ -829,7 +829,8 @@ dhcp_inform(struct netif *netif) void dhcp_network_changed(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); + if (!dhcp) return; switch (dhcp->state) { @@ -862,7 +863,8 @@ dhcp_network_changed(struct netif *netif) #if DHCP_DOES_ARP_CHECK /** - * Match an ARP reply with the offered IP address. + * Match an ARP reply with the offered IP address: + * check whether the offered IP address is not in use using ARP * * @param netif the network interface on which the reply was received * @param addr The IP address we received a reply from @@ -870,15 +872,18 @@ dhcp_network_changed(struct netif *netif) void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) { + struct dhcp *dhcp; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); /* is a DHCP client doing an ARP check? */ - if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_STATE_CHECKING)) { + if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", ip4_addr_get_u32(addr))); /* did a host respond with the address we were offered by the DHCP server? */ - if (ip4_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) { /* we will not accept the offered address */ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); @@ -899,7 +904,7 @@ dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) static err_t dhcp_decline(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result = ERR_OK; u16_t msecs; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); @@ -908,14 +913,14 @@ dhcp_decline(struct netif *netif) result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); if (result == ERR_OK) { dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); dhcp_option_trailer(dhcp); /* resize pbuf to reflect true size of options */ pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); /* per section 4.4.4, broadcast DECLINE messages */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); } else { @@ -941,7 +946,7 @@ dhcp_decline(struct netif *netif) static err_t dhcp_discover(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result = ERR_OK; u16_t msecs; u8_t i; @@ -966,7 +971,7 @@ dhcp_discover(struct netif *netif) pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); @@ -1001,7 +1006,7 @@ dhcp_bind(struct netif *netif) struct dhcp *dhcp; ip4_addr_t sn_mask, gw_addr; LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); - dhcp = netif->dhcp; + dhcp = netif_dhcp_data(netif); LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); @@ -1107,7 +1112,7 @@ dhcp_bind(struct netif *netif) err_t dhcp_renew(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; u16_t msecs; u8_t i; @@ -1159,7 +1164,7 @@ dhcp_renew(struct netif *netif) static err_t dhcp_rebind(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; u16_t msecs; u8_t i; @@ -1209,7 +1214,7 @@ dhcp_rebind(struct netif *netif) static err_t dhcp_reboot(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; u16_t msecs; u8_t i; @@ -1220,10 +1225,10 @@ dhcp_reboot(struct netif *netif) result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, 576); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { @@ -1253,14 +1258,14 @@ dhcp_reboot(struct netif *netif) /** * @ingroup dhcp4 - * Release a DHCP lease. + * Release a DHCP lease (usually called before @ref dhcp_stop). * * @param netif network interface which must release its lease */ err_t dhcp_release(struct netif *netif) { - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); err_t result; ip_addr_t server_ip_addr; u8_t is_dhcp_supplied_address; @@ -1295,7 +1300,7 @@ dhcp_release(struct netif *netif) result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); if (result == ERR_OK) { dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); dhcp_option_trailer(dhcp); @@ -1309,7 +1314,7 @@ dhcp_release(struct netif *netif) LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); } /* remove IP address from interface (prevents routing from selecting this interface) */ - netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); return result; } @@ -1325,7 +1330,7 @@ dhcp_stop(struct netif *netif) { struct dhcp *dhcp; LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); - dhcp = netif->dhcp; + dhcp = netif_dhcp_data(netif); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); /* netif is DHCP configured? */ @@ -1410,14 +1415,15 @@ dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) if (netif->hostname != NULL) { size_t namelen = strlen(netif->hostname); if (namelen > 0) { - u8_t len; + size_t len; const char *p = netif->hostname; /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME and 1 byte for trailer) */ size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); len = LWIP_MIN(namelen, available); - dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); + LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len); while (len--) { dhcp_option_byte(dhcp, *p++); } @@ -1487,7 +1493,7 @@ again: int decode_idx = -1; u16_t val_offset = offset + 2; /* len byte might be in the next pbuf */ - if (offset + 1 < q->len) { + if ((offset + 1) < q->len) { len = options[offset + 1]; } else { len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); @@ -1513,7 +1519,7 @@ again: break; case(DHCP_OPTION_DNS_SERVER): /* special case: there might be more than one server */ - LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); /* limit number of DNS servers */ decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); @@ -1526,7 +1532,7 @@ again: #if LWIP_DHCP_GET_NTP_SRV case(DHCP_OPTION_NTP): /* special case: there might be more than one server */ - LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); /* limit number of NTP servers */ decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); @@ -1566,18 +1572,20 @@ decode_next: LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); if (!dhcp_option_given(dhcp, decode_idx)) { copy_len = LWIP_MIN(decode_len, 4); - pbuf_copy_partial(q, &value, copy_len, val_offset); + if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) { + return ERR_BUF; + } if (decode_len > 4) { /* decode more than one u32_t */ - LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, htonl(value)); + dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); decode_len -= 4; val_offset += 4; decode_idx++; goto decode_next; } else if (decode_len == 4) { - value = ntohl(value); + value = lwip_ntohl(value); } else { LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); value = ((u8_t*)&value)[0]; @@ -1622,7 +1630,9 @@ decode_next: if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) /* copy bootp file name, don't care for sname (server hostname) */ - pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) { + return ERR_BUF; + } /* make sure the string is really NULL-terminated */ dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; } @@ -1650,11 +1660,11 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { struct netif *netif = ip_current_input_netif(); - struct dhcp *dhcp = netif->dhcp; + struct dhcp *dhcp = netif_dhcp_data(netif); struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; u8_t msg_type; u8_t i; - + LWIP_UNUSED_ARG(arg); /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ @@ -1663,7 +1673,7 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, } LWIP_ASSERT("invalid server address type", IP_IS_V4(addr)); - + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); @@ -1694,9 +1704,9 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, } } /* match transaction ID against what we expected */ - if (ntohl(reply_msg->xid) != dhcp->xid) { + if (lwip_ntohl(reply_msg->xid) != dhcp->xid) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid)); goto free_pbuf_and_return; } /* option fields could be unfold? */ @@ -1825,7 +1835,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) dhcp->msg_out->htype = DHCP_HTYPE_ETH; dhcp->msg_out->hlen = netif->hwaddr_len; dhcp->msg_out->hops = 0; - dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->xid = lwip_htonl(dhcp->xid); dhcp->msg_out->secs = 0; /* we don't need the broadcast flag since we can receive unicast traffic before being fully configured! */ @@ -1912,11 +1922,9 @@ dhcp_option_trailer(struct dhcp *dhcp) u8_t dhcp_supplied_address(const struct netif *netif) { - if ((netif != NULL) && (netif->dhcp != NULL)) { - if ((netif->dhcp->state == DHCP_STATE_BOUND) || - (netif->dhcp->state == DHCP_STATE_RENEWING)) { - return 1; - } + if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { + struct dhcp* dhcp = netif_dhcp_data(netif); + return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING); } return 0; } diff --git a/src/core/ipv4/etharp.c b/src/core/ipv4/etharp.c index 5481d3bd..bf4dad53 100644 --- a/src/core/ipv4/etharp.c +++ b/src/core/ipv4/etharp.c @@ -52,6 +52,7 @@ #include "lwip/snmp.h" #include "lwip/dhcp.h" #include "lwip/autoip.h" +#include "netif/ethernet.h" #include @@ -71,8 +72,7 @@ */ #define ARP_MAXPENDING 5 -#define HWTYPE_ETHERNET 1 - +/** ARP states */ enum etharp_state { ETHARP_STATE_EMPTY = 0, ETHARP_STATE_PENDING, @@ -240,7 +240,7 @@ etharp_tmr(void) * old entries. Heuristic choose the least important entry for recycling. * * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags @see definition of ETHARP_FLAG_* + * @param flags See @ref etharp_state * @param netif netif related to this address (used for NETIF_HWADDRHINT) * * @return The ARP entry index that matched or is created, ERR_MEM if no @@ -394,47 +394,6 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) return (err_t)i; } -/** - * Send an IP packet on the network using netif->linkoutput - * The ethernet header is filled in before sending. - * - * @params netif the lwIP network interface on which to send the packet - * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header - * @params src the source MAC address to be copied into the ethernet header - * @params dst the destination MAC address to be copied into the ethernet header - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -static err_t -etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const struct eth_addr *dst) -{ - struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - struct eth_vlan_hdr *vlanhdr; -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETH_HWADDR_LEN)); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - ethhdr->type = PP_HTONS(ETHTYPE_VLAN); - vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); - vlanhdr->prio_vid = 0; - vlanhdr->tpid = PP_HTONS(ETHTYPE_IP); - if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { - /* packet shall not contain VLAN header, so hide it and set correct ethertype */ - pbuf_header(p, -SIZEOF_VLAN_HDR); - ethhdr = (struct eth_hdr *)p->payload; -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - ethhdr->type = PP_HTONS(ETHTYPE_IP); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - } -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - ETHADDR32_COPY(ðhdr->dest, dst); - ETHADDR16_COPY(ðhdr->src, src); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); - /* send the packet */ - return netif->linkoutput(netif, p); -} - /** * Update (or insert) a IP/MAC address pair in the ARP cache. * @@ -444,7 +403,7 @@ etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags @see definition of ETHARP_FLAG_* + * @param flags See @ref etharp_state * * @return * - ERR_OK Successfully updated ARP cache. @@ -518,7 +477,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et arp_table[i].q = NULL; #endif /* ARP_QUEUEING */ /* send the queued IP packet */ - etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); /* free the queued IP packet */ pbuf_free(p); } @@ -532,7 +491,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry - * @return @see return values of etharp_add_static_entry + * @return See return values of etharp_add_static_entry */ err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) @@ -658,56 +617,6 @@ etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_a } } -#if ETHARP_TRUST_IP_MAC -/** - * Updates the ARP table using the given IP packet. - * - * Uses the incoming IP packet's source address to update the - * ARP cache for the local network. The function does not alter - * or free the packet. This function must be called before the - * packet p is passed to the IP layer. - * - * @param netif The lwIP network interface on which the IP packet pbuf arrived. - * @param p The IP packet that arrived on netif. - * - * @return NULL - * - * @see pbuf_free() - */ -void -etharp_ip_input(struct netif *netif, struct pbuf *p) -{ - struct eth_hdr *ethhdr; - struct ip_hdr *iphdr; - ip4_addr_t iphdr_src; - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - /* Only insert an entry if the source IP address of the - incoming IP packet comes from a host on the local network. */ - ethhdr = (struct eth_hdr *)p->payload; - iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); -#if ETHARP_SUPPORT_VLAN - if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { - iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); - } -#endif /* ETHARP_SUPPORT_VLAN */ - - ip4_addr_copy(iphdr_src, iphdr->src); - - /* source is not on the local network? */ - if (!ip4_addr_netcmp(&iphdr_src, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { - /* do nothing */ - return; - } - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); - /* update the source IP address in the cache, if present */ - /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk - * back soon (for example, if the destination IP address is ours. */ - etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); -} -#endif /* ETHARP_TRUST_IP_MAC */ - /** * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache * send out queued IP packets. Updates cache with snooped address pairs. @@ -715,47 +624,22 @@ etharp_ip_input(struct netif *netif, struct pbuf *p) * Should be called for incoming ARP packets. The pbuf in the argument * is freed by this function. * - * @param netif The lwIP network interface on which the ARP packet pbuf arrived. - * @param ethaddr Ethernet address of netif. * @param p The ARP packet that arrived on netif. Is freed by this function. - * - * @return NULL + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. * * @see pbuf_free() */ void -etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +etharp_input(struct pbuf *p, struct netif *netif) { struct etharp_hdr *hdr; - struct eth_hdr *ethhdr; /* these are aligned properly, whereas the ARP header fields might not be */ ip4_addr_t sipaddr, dipaddr; u8_t for_us; -#if LWIP_AUTOIP - const u8_t * ethdst_hwaddr; -#endif /* LWIP_AUTOIP */ LWIP_ERROR("netif != NULL", (netif != NULL), return;); - /* drop short ARP packets: we have to check for p->len instead of p->tot_len here - since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ - if (p->len < SIZEOF_ETHARP_PACKET) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, - (s16_t)SIZEOF_ETHARP_PACKET)); - ETHARP_STATS_INC(etharp.lenerr); - ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - return; - } - - ethhdr = (struct eth_hdr *)p->payload; - hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); -#if ETHARP_SUPPORT_VLAN - if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { - hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); - } -#endif /* ETHARP_SUPPORT_VLAN */ + hdr = (struct etharp_hdr *)p->payload; /* RFC 826 "Packet Reception": */ if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || @@ -763,7 +647,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) (hdr->protolen != sizeof(ip4_addr_t)) || (hdr->proto != PP_HTONS(ETHTYPE_IP))) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen)); ETHARP_STATS_INC(etharp.proterr); ETHARP_STATS_INC(etharp.drop); @@ -808,55 +692,54 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) * reply. In any case, we time-stamp any existing ARP entry, * and possibly send out an IP packet that was queued on it. */ - LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); /* ARP request for our address? */ if (for_us) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n")); /* Re-use pbuf to send ARP reply. Since we are re-using an existing pbuf, we can't call etharp_raw since that would allocate a new pbuf. */ - hdr->opcode = htons(ARP_REPLY); + hdr->opcode = lwip_htons(ARP_REPLY); IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif)); LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETH_HWADDR_LEN)); -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - ethdst_hwaddr = ip4_addr_islinklocal(netif_ip4_addr(netif)) ? (const u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; -#endif /* LWIP_AUTOIP */ - - ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); -#if LWIP_AUTOIP - ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); -#else /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); -#endif /* LWIP_AUTOIP */ - ETHADDR16_COPY(&hdr->shwaddr, ethaddr); - ETHADDR16_COPY(ðhdr->src, ethaddr); /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header are already correct, we tested that before */ + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); + ETHADDR16_COPY(&hdr->shwaddr, netif->hwaddr); + /* return ARP reply */ - netif->linkoutput(netif, p); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { + ethernet_output(netif, p, &hdr->shwaddr, ðbroadcast, ETHTYPE_ARP); + } else +#endif /* LWIP_AUTOIP */ + { + ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP); + } + /* we are not configured? */ } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { /* { for_us == 0 and netif->ip_addr.addr == 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n")); /* request was not directed to us */ } else { /* { for_us == 0 and netif->ip_addr.addr != 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n")); } break; case PP_HTONS(ARP_REPLY): /* ARP reply. We already updated the ARP cache earlier. */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n")); #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) /* DHCP wants to know about ARP replies from any host with an * IP address also offered to us by the DHCP server. We do not @@ -866,7 +749,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) #endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ break; default: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode))); ETHARP_STATS_INC(etharp.err); break; } @@ -899,8 +782,7 @@ etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) } } - return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), - &arp_table[arp_idx].ethaddr); + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP); } /** @@ -919,7 +801,7 @@ etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) * * @return * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or etharp_send_ip(). + * or the return type of either etharp_query() or ethernet_output(). */ err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) @@ -932,19 +814,6 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) LWIP_ASSERT("q != NULL", q != NULL); LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - /* make room for Ethernet header - should not fail */ -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - if (pbuf_header(q, sizeof(struct eth_hdr) + SIZEOF_VLAN_HDR) != 0) { -#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - /* bail out */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_output: could not allocate room for header.\n")); - LINK_STATS_INC(link.lenerr); - return ERR_BUF; - } - /* Determine on destination hardware address. Broadcasts and multicasts * are special, other IP addresses are looked up in the ARP table. */ @@ -971,11 +840,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && !ip4_addr_islinklocal(ipaddr)) { #if LWIP_AUTOIP - struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - SIZEOF_VLAN_HDR + -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - sizeof(struct eth_hdr)); + struct ip_hdr *iphdr = (struct ip_hdr*)(size_t)q->payload; /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with a link-local source address must always be "directly to its destination on the same physical link. The host MUST NOT send the packet to any @@ -1009,6 +874,9 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) if (etharp_cached_entry < ARP_TABLE_SIZE) { #endif /* LWIP_NETIF_HWADDRHINT */ if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[etharp_cached_entry].netif == netif) && +#endif (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { /* the per-pcb-cached entry is stable and the right one! */ ETHARP_STATS_INC(etharp.cachehit); @@ -1023,6 +891,9 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) throughput and etharp_find_entry() is kind of slow */ for (i = 0; i < ARP_TABLE_SIZE; i++) { if ((arp_table[i].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[i].netif == netif) && +#endif (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { /* found an existing, stable entry */ ETHARP_SET_HINT(netif, i); @@ -1037,7 +908,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) /* continuation for multicast/broadcast destinations */ /* obtain source Ethernet address of the given interface */ /* send packet directly on the link */ - return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP); } /** @@ -1137,7 +1008,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) /* we have a valid IP->Ethernet address mapping */ ETHARP_SET_HINT(netif, i); /* send the packet */ - result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP); /* pending entry? (either just created or already pending */ } else if (arp_table[i].state == ETHARP_STATE_PENDING) { /* entry is still pending, queue the given packet 'q' */ @@ -1157,7 +1028,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) } if (copy_needed) { /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM); + p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); if (p != NULL) { if (pbuf_copy(p, q) != ERR_OK) { pbuf_free(p); @@ -1245,10 +1116,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) * ERR_MEM if the ARP packet couldn't be allocated * any other err_t on failure */ -#if !LWIP_AUTOIP -static -#endif /* LWIP_AUTOIP */ -err_t +static err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, @@ -1257,19 +1125,12 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, { struct pbuf *p; err_t result = ERR_OK; - struct eth_hdr *ethhdr; -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - struct eth_vlan_hdr *vlanhdr; -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ struct etharp_hdr *hdr; -#if LWIP_AUTOIP - const u8_t * ethdst_hwaddr; -#endif /* LWIP_AUTOIP */ LWIP_ASSERT("netif != NULL", netif != NULL); /* allocate a pbuf for the outgoing ARP request packet */ - p = pbuf_alloc(PBUF_RAW_TX, SIZEOF_ETHARP_PACKET_TX, PBUF_RAM); + p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM); /* could allocate a pbuf for an ARP request? */ if (p == NULL) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, @@ -1278,26 +1139,15 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, return ERR_MEM; } LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", - (p->len >= SIZEOF_ETHARP_PACKET_TX)); + (p->len >= SIZEOF_ETHARP_HDR)); - ethhdr = (struct eth_hdr *)p->payload; -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); - hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); -#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + hdr = (struct etharp_hdr *)p->payload; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); - hdr->opcode = htons(opcode); + hdr->opcode = lwip_htons(opcode); LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETH_HWADDR_LEN)); -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - ethdst_hwaddr = ip4_addr_islinklocal(ipsrc_addr) ? (const u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; -#endif /* LWIP_AUTOIP */ + /* Write the ARP MAC-Addresses */ ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); @@ -1312,30 +1162,19 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, hdr->hwlen = ETH_HWADDR_LEN; hdr->protolen = sizeof(ip4_addr_t); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - ethhdr->type = PP_HTONS(ETHTYPE_VLAN); - vlanhdr->tpid = PP_HTONS(ETHTYPE_ARP); - vlanhdr->prio_vid = 0; - if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { - /* packet shall not contain VLAN header, so hide it and set correct ethertype */ - pbuf_header(p, -SIZEOF_VLAN_HDR); - ethhdr = (struct eth_hdr *)p->payload; -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - ethhdr->type = PP_HTONS(ETHTYPE_ARP); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - } -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - - /* Write the Ethernet MAC-Addresses */ -#if LWIP_AUTOIP - ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); -#else /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->dest, ethdst_addr); -#endif /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->src, ethsrc_addr); - /* send ARP query */ - result = netif->linkoutput(netif, p); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + if(ip4_addr_islinklocal(ipsrc_addr)) { + ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP); + } else +#endif /* LWIP_AUTOIP */ + { + ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP); + } + ETHARP_STATS_INC(etharp.xmit); /* free ARP query packet */ pbuf_free(p); diff --git a/src/core/ipv4/icmp.c b/src/core/ipv4/icmp.c index d6348d89..e60e4481 100644 --- a/src/core/ipv4/icmp.c +++ b/src/core/ipv4/icmp.c @@ -236,7 +236,7 @@ icmp_input(struct pbuf *p, struct netif *inp) MIB2_STATS_INC(mib2.icmpoutechoreps); /* send an ICMP packet */ - ret = ip4_output_if(p, src, IP_HDRINCL, + ret = ip4_output_if(p, src, LWIP_IP_HDRINCL, ICMP_TTL, 0, IP_PROTO_ICMP, inp); if (ret != ERR_OK) { LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 50c5d9d0..5ae7d9c8 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -2,6 +2,9 @@ * @file * IGMP - Internet Group Management Protocol * + * @defgroup igmp IGMP + * @ingroup ip4 + * To be called from TCPIP thread */ /* @@ -38,12 +41,6 @@ * source code. */ -/** - * @defgroup igmp IGMP - * @ingroup ip4 - * To be called from TCPIP thread - */ - /*------------------------------------------------------------- Note 1) Although the rfc requires V1 AND V2 capability @@ -95,63 +92,21 @@ Steve Reynolds #include "lwip/inet_chksum.h" #include "lwip/netif.h" #include "lwip/stats.h" +#include "lwip/prot/igmp.h" #include "string.h" -/* - * IGMP constants - */ -#define IGMP_TTL 1 -#define IGMP_MINLEN 8 -#define ROUTER_ALERT 0x9404U -#define ROUTER_ALERTLEN 4 - -/* - * IGMP message types, including version number. - */ -#define IGMP_MEMB_QUERY 0x11 /* Membership query */ -#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ -#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ -#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ - -/* Group membership states */ -#define IGMP_GROUP_NON_MEMBER 0 -#define IGMP_GROUP_DELAYING_MEMBER 1 -#define IGMP_GROUP_IDLE_MEMBER 2 - -/** - * IGMP packet format. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct igmp_msg { - PACK_STRUCT_FLD_8(u8_t igmp_msgtype); - PACK_STRUCT_FLD_8(u8_t igmp_maxresp); - PACK_STRUCT_FIELD(u16_t igmp_checksum); - PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); -static err_t igmp_remove_group(struct igmp_group *group); -static void igmp_timeout( struct igmp_group *group); +static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group); +static void igmp_timeout(struct netif *netif, struct igmp_group *group); static void igmp_start_timer(struct igmp_group *group, u8_t max_time); static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); -static void igmp_send(struct igmp_group *group, u8_t type); +static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type); - -static struct igmp_group* igmp_group_list; static ip4_addr_t allsystems; static ip4_addr_t allrouters; - /** * Initialize the IGMP module */ @@ -187,7 +142,7 @@ igmp_start(struct netif *netif) LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER); } return ERR_OK; @@ -204,36 +159,24 @@ igmp_start(struct netif *netif) err_t igmp_stop(struct netif *netif) { - struct igmp_group *group = igmp_group_list; - struct igmp_group *prev = NULL; - struct igmp_group *next; + struct igmp_group *group = netif_igmp_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL); - /* look for groups joined on this interface further down the list */ while (group != NULL) { - next = group->next; - /* is it a group joined on this interface? */ - if (group->netif == netif) { - /* is it the first group of the list? */ - if (group == igmp_group_list) { - igmp_group_list = next; - } - /* is there a "previous" group defined? */ - if (prev != NULL) { - prev->next = next; - } - /* disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); - ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); - } - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); - } else { - /* change the "previous" */ - prev = group; + struct igmp_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); } + + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + /* move to "next" */ group = next; } @@ -248,14 +191,17 @@ igmp_stop(struct netif *netif) void igmp_report_groups(struct netif *netif) { - struct igmp_group *group = igmp_group_list; + struct igmp_group *group = netif_igmp_data(netif); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(group != NULL) { + group = group->next; + } + while (group != NULL) { - if ((group->netif == netif) && (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { - igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - } + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); group = group->next; } } @@ -271,10 +217,10 @@ igmp_report_groups(struct netif *netif) struct igmp_group * igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) { - struct igmp_group *group = igmp_group_list; + struct igmp_group *group = netif_igmp_data(ifp); while (group != NULL) { - if ((group->netif == ifp) && (ip4_addr_cmp(&(group->group_address), addr))) { + if (ip4_addr_cmp(&(group->group_address), addr)) { return group; } group = group->next; @@ -309,15 +255,14 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) /* Group doesn't exist yet, create a new one */ group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); if (group != NULL) { - group->netif = ifp; ip4_addr_set(&(group->group_address), addr); group->timer = 0; /* Not running */ group->group_state = IGMP_GROUP_NON_MEMBER; group->last_reporter_flag = 0; group->use = 0; - group->next = igmp_group_list; + group->next = netif_igmp_data(ifp); - igmp_group_list = group; + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); } LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); @@ -328,23 +273,23 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) } /** - * Remove a group in the global igmp_group_list + * Remove a group in the global igmp_group_list, but don't free it yet * * @param group the group to remove from the global igmp_group_list * @return ERR_OK if group was removed from the list, an err_t otherwise */ static err_t -igmp_remove_group(struct igmp_group *group) +igmp_remove_group(struct netif* netif, struct igmp_group *group) { err_t err = ERR_OK; /* Is it the first group? */ - if (igmp_group_list == group) { - igmp_group_list = group->next; + if (netif_igmp_data(netif) == group) { + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next); } else { /* look for group further down the list */ struct igmp_group *tmpGroup; - for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { if (tmpGroup->next == group) { tmpGroup->next = group->next; break; @@ -355,8 +300,6 @@ igmp_remove_group(struct igmp_group *group) err = ERR_ARG; } } - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); return err; } @@ -427,12 +370,16 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) IGMP_STATS_INC(igmp.rx_general); } - groupref = igmp_group_list; + groupref = netif_igmp_data(inp); + + /* Do not send messages on the all systems group address! */ + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(groupref != NULL) { + groupref = groupref->next; + } + while (groupref) { - /* Do not send messages on the all systems group address! */ - if ((groupref->netif == inp) && (!(ip4_addr_cmp(&(groupref->group_address), &allsystems)))) { - igmp_delaying_member(groupref, igmp->igmp_maxresp); - } + igmp_delaying_member(groupref, igmp->igmp_maxresp); groupref = groupref->next; } } else { @@ -473,7 +420,7 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) break; default: LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", - igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)group->netif)); + igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp)); IGMP_STATS_INC(igmp.proterr); break; } @@ -557,11 +504,11 @@ igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); ip4_addr_debug_print(IGMP_DEBUG, groupaddr); LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); } IGMP_STATS_INC(igmp.tx_join); - igmp_send(group, IGMP_V2_MEMB_REPORT); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); @@ -645,11 +592,14 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) /* If there is no other use of the group */ if (group->use <= 1) { + /* Remove the group from the list */ + igmp_remove_group(netif, group); + /* If we are the last reporter for this group */ if (group->last_reporter_flag) { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); IGMP_STATS_INC(igmp.tx_leave); - igmp_send(group, IGMP_LEAVE_GROUP); + igmp_send(netif, group, IGMP_LEAVE_GROUP); } /* Disable the group at the MAC level */ @@ -657,15 +607,11 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); ip4_addr_debug_print(IGMP_DEBUG, groupaddr); LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); } - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: remove group: ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* Free the group */ - igmp_remove_group(group); + /* Free group struct */ + memp_free(MEMP_IGMP_GROUP, group); } else { /* Decrement group use */ group->use--; @@ -684,16 +630,21 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) void igmp_tmr(void) { - struct igmp_group *group = igmp_group_list; + struct netif *netif = netif_list; - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - igmp_timeout(group); + while (netif != NULL) { + struct igmp_group *group = netif_igmp_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(netif, group); + } } + group = group->next; } - group = group->next; + netif = netif->next; } } @@ -704,7 +655,7 @@ igmp_tmr(void) * @param group an igmp_group for which a timeout is reached */ static void -igmp_timeout(struct igmp_group *group) +igmp_timeout(struct netif *netif, struct igmp_group *group) { /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group (unless it is the allsystems group) */ @@ -712,10 +663,12 @@ igmp_timeout(struct igmp_group *group) (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)group->netif)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); + group->group_state = IGMP_GROUP_IDLE_MEMBER; + IGMP_STATS_INC(igmp.tx_report); - igmp_send(group, IGMP_V2_MEMB_REPORT); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); } } @@ -765,13 +718,11 @@ igmp_delaying_member(struct igmp_group *group, u8_t maxresp) * the IP address of the outgoing network interface is filled in as source address. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header * @param netif the netif on which to send this packet * @return ERR_OK if the packet was sent OK * ERR_BUF if p doesn't have enough space for IP/LINK headers @@ -795,11 +746,11 @@ igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, * @param type the type of igmp packet to send */ static void -igmp_send(struct igmp_group *group, u8_t type) +igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) { struct pbuf* p = NULL; struct igmp_msg* igmp = NULL; - ip4_addr_t src = *IP4_ADDR_ANY; + ip4_addr_t src = *IP4_ADDR_ANY4; ip4_addr_t* dest = NULL; /* IP header + "router alert" option + IGMP header */ @@ -809,7 +760,7 @@ igmp_send(struct igmp_group *group, u8_t type) igmp = (struct igmp_msg *)p->payload; LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", (p->len >= sizeof(struct igmp_msg))); - ip4_addr_copy(src, *netif_ip4_addr(group->netif)); + ip4_addr_copy(src, *netif_ip4_addr(netif)); if (type == IGMP_V2_MEMB_REPORT) { dest = &(group->group_address); @@ -828,7 +779,7 @@ igmp_send(struct igmp_group *group, u8_t type) igmp->igmp_checksum = 0; igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); - igmp_ip_output_if(p, &src, dest, group->netif); + igmp_ip_output_if(p, &src, dest, netif); } pbuf_free(p); diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 1bdc30f5..c7836774 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -53,9 +53,9 @@ #include "lwip/raw.h" #include "lwip/udp.h" #include "lwip/priv/tcp_priv.h" -#include "lwip/dhcp.h" #include "lwip/autoip.h" #include "lwip/stats.h" +#include "lwip/prot/dhcp.h" #include @@ -106,7 +106,9 @@ static u16_t ip_id; /** The default netif used for multicast */ static struct netif* ip4_default_multicast_netif; -/** Set a default netif for IPv4 multicast. */ +/** + * @ingroup ip4 + * Set a default netif for IPv4 multicast. */ void ip4_set_default_multicast_netif(struct netif* default_multicast_netif) { @@ -220,13 +222,12 @@ ip4_route(const ip4_addr_t *dest) * that may not be forwarded, or whether datagrams to that destination * may be forwarded. * @param p the packet to forward - * @param dest the destination IP address * @return 1: can forward 0: discard */ static int ip4_canforward(struct pbuf *p) { - u32_t addr = htonl(ip4_addr_get_u32(ip4_current_dest_addr())); + u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); if (p->flags & PBUF_FLAG_LLBCAST) { /* don't route link-layer broadcasts */ @@ -265,6 +266,7 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) struct netif *netif; PERF_START; + LWIP_UNUSED_ARG(inp); if (!ip4_canforward(p)) { goto return_noroute; @@ -402,7 +404,7 @@ ip4_input(struct pbuf *p, struct netif *inp) /* calculate IP header length in bytes */ iphdr_hlen *= 4; /* obtain ip length in bytes */ - iphdr_len = ntohs(IPH_LEN(iphdr)); + iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); /* Trim pbuf. This is especially required for packets < 60 bytes. */ if (iphdr_len < p->tot_len) { @@ -507,8 +509,7 @@ ip4_input(struct pbuf *p, struct netif *inp) #if LWIP_AUTOIP /* connections to link-local addresses must persist after changing the netif's address (RFC3927 ch. 1.9) */ - if ((netif->autoip != NULL) && - ip4_addr_cmp(ip4_current_dest_addr(), &(netif->autoip->llipaddr))) { + if (autoip_accept_packet(netif, ip4_current_dest_addr())) { LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", netif->name[0], netif->name[1])); /* break out of for loop */ @@ -543,7 +544,7 @@ ip4_input(struct pbuf *p, struct netif *inp) if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", - ntohs(udphdr->dest))); + lwip_ntohs(udphdr->dest))); if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); netif = inp; @@ -598,7 +599,7 @@ ip4_input(struct pbuf *p, struct netif *inp) if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { #if IP_REASSEMBLY /* packet fragment reassembly code present? */ LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", - ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); + lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); /* reassemble the packet*/ p = ip4_reass(p); /* packet not fully reassembled yet? */ @@ -609,7 +610,7 @@ ip4_input(struct pbuf *p, struct netif *inp) #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ pbuf_free(p); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", - ntohs(IPH_OFFSET(iphdr)))); + lwip_ntohs(IPH_OFFSET(iphdr)))); IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.drop); /* unsupported protocol feature */ @@ -716,13 +717,13 @@ ip4_input(struct pbuf *p, struct netif *inp) * the IP header and calculates the IP header checksum. If the source * IP address is NULL, the IP address of the outgoing network * interface is filled in as source address. - * If the destination IP address is IP_HDRINCL, p is assumed to already + * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already * include an IP header and p->payload points to it instead of the data. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header @@ -758,7 +759,7 @@ ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, { #endif /* IP_OPTIONS_SEND */ const ip4_addr_t *src_used = src; - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { if (ip4_addr_isany(src)) { src_used = netif_ip4_addr(netif); } @@ -806,7 +807,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d MIB2_STATS_INC(mib2.ipoutrequests); /* Should the IP header be generated or is it already included in p? */ - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { u16_t ip_hlen = IP_HLEN; #if IP_OPTIONS_SEND u16_t optlen_aligned = 0; @@ -867,19 +868,19 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d #if CHECKSUM_GEN_IP_INLINE chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); #endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_LEN_SET(iphdr, htons(p->tot_len)); + IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); #if CHECKSUM_GEN_IP_INLINE chk_sum += iphdr->_len; #endif /* CHECKSUM_GEN_IP_INLINE */ IPH_OFFSET_SET(iphdr, 0); - IPH_ID_SET(iphdr, htons(ip_id)); + IPH_ID_SET(iphdr, lwip_htons(ip_id)); #if CHECKSUM_GEN_IP_INLINE chk_sum += iphdr->_id; #endif /* CHECKSUM_GEN_IP_INLINE */ ++ip_id; if (src == NULL) { - ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY); + ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); } else { /* src cannot be NULL here */ ip4_addr_copy(iphdr->src, *src); @@ -951,9 +952,9 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d * interface and calls upon ip_output_if to do the actual work. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header @@ -986,9 +987,9 @@ ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, * before calling ip_output_if. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header @@ -1039,19 +1040,19 @@ ip4_debug_print(struct pbuf *p) (u16_t)IPH_V(iphdr), (u16_t)IPH_HL(iphdr), (u16_t)IPH_TOS(iphdr), - ntohs(IPH_LEN(iphdr)))); + lwip_ntohs(IPH_LEN(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", - ntohs(IPH_ID(iphdr)), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); + lwip_ntohs(IPH_ID(iphdr)), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", (u16_t)IPH_TTL(iphdr), (u16_t)IPH_PROTO(iphdr), - ntohs(IPH_CHKSUM(iphdr)))); + lwip_ntohs(IPH_CHKSUM(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", ip4_addr1_16(&iphdr->src), diff --git a/src/core/ipv4/ip4_addr.c b/src/core/ipv4/ip4_addr.c index 7fe35c98..eb812afb 100644 --- a/src/core/ipv4/ip4_addr.c +++ b/src/core/ipv4/ip4_addr.c @@ -43,7 +43,7 @@ #include "lwip/ip_addr.h" #include "lwip/netif.h" -/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); @@ -260,7 +260,7 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) break; } if (addr) { - ip4_addr_set_u32(addr, htonl(val)); + ip4_addr_set_u32(addr, lwip_htonl(val)); } return 1; } diff --git a/src/core/ipv4/ip4_frag.c b/src/core/ipv4/ip4_frag.c index b18d904e..b6f90945 100644 --- a/src/core/ipv4/ip4_frag.c +++ b/src/core/ipv4/ip4_frag.c @@ -160,7 +160,7 @@ static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) { u16_t pbufs_freed = 0; - u8_t clen; + u16_t clen; struct pbuf *p; struct ip_reass_helper *iprh; @@ -331,7 +331,7 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) * will grow over time as new pbufs are rx. * Also checks that the datagram passes basic continuity checks (if the last * fragment was received at least once). - * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param ipr points to the reassembly state * @param new_p points to the pbuf for the current fragment * @return 0 if invalid, >0 otherwise */ @@ -340,14 +340,14 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct { struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; struct pbuf *q; - u16_t offset,len; + u16_t offset, len; struct ip_hdr *fraghdr; int valid = 1; /* Extract length and fragment offset from current fragment */ fraghdr = (struct ip_hdr*)new_p->payload; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; /* overwrite the fragment's ip header from the pbuf with our helper struct, * and setup the embedded helper structure. */ @@ -487,8 +487,7 @@ ip4_reass(struct pbuf *p) struct ip_hdr *fraghdr; struct ip_reassdata *ipr; struct ip_reass_helper *iprh; - u16_t offset, len; - u8_t clen; + u16_t offset, len, clen; IPFRAG_STATS_INC(ip_frag.recv); MIB2_STATS_INC(mib2.ipreasmreqds); @@ -501,8 +500,8 @@ ip4_reass(struct pbuf *p) goto nullreturn; } - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; /* Check if we are allowed to enqueue more datagrams. */ clen = pbuf_clen(p); @@ -530,7 +529,7 @@ ip4_reass(struct pbuf *p) fragment into the buffer. */ if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", - ntohs(IPH_ID(fraghdr)))); + lwip_ntohs(IPH_ID(fraghdr)))); IPFRAG_STATS_INC(ip_frag.cachehit); break; } @@ -544,8 +543,8 @@ ip4_reass(struct pbuf *p) goto nullreturn; } } else { - if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { /* ipr->iphdr is not the header from the first fragment, but fraghdr is * -> copy fraghdr into ipr->iphdr since we want to have the header * of the first fragment (for ICMP time exceeded and later, for copying @@ -582,7 +581,7 @@ ip4_reass(struct pbuf *p) /* copy the original ip header back to the first pbuf */ fraghdr = (struct ip_hdr*)(ipr->p->payload); SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); IPH_OFFSET_SET(fraghdr, 0); IPH_CHKSUM_SET(fraghdr, 0); /* @todo: do we need to set/calculate the correct checksum? */ @@ -639,10 +638,6 @@ nullreturn: #endif /* IP_REASSEMBLY */ #if IP_FRAG -#if IP_FRAG_USES_STATIC_BUF -static LWIP_DECLARE_MEMORY_ALIGNED(buf, IP_FRAG_MAX_MTU); -#else /* IP_FRAG_USES_STATIC_BUF */ - #if !LWIP_NETIF_TX_SINGLE_PBUF /** Allocate a new struct pbuf_custom_ref */ static struct pbuf_custom_ref* @@ -673,14 +668,12 @@ ipfrag_free_pbuf_custom(struct pbuf *p) ip_frag_free_pbuf_custom_ref(pcr); } #endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ /** * Fragment an IP datagram if too large for the netif. * * Chop the datagram in MTU sized chunks and send them in order - * by using a fixed size static memory buffer (PBUF_REF) or - * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * by pointing PBUF_REFs into p. * * @param p ip packet to send * @param netif the netif on which to send @@ -692,81 +685,45 @@ err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) { struct pbuf *rambuf; -#if IP_FRAG_USES_STATIC_BUF - struct pbuf *header; -#else #if !LWIP_NETIF_TX_SINGLE_PBUF struct pbuf *newpbuf; #endif struct ip_hdr *original_iphdr; -#endif struct ip_hdr *iphdr; - u16_t nfb; - u16_t left, cop; - u16_t mtu = netif->mtu; - u16_t ofo, omf; - u16_t last; + const u16_t nfb = (netif->mtu - IP_HLEN) / 8; + u16_t left, fragsize; + u16_t ofo; + int last; u16_t poff = IP_HLEN; u16_t tmp; -#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +#if !LWIP_NETIF_TX_SINGLE_PBUF u16_t newpbuflen = 0; u16_t left_to_copy; #endif - /* Get a RAM based MTU sized pbuf */ -#if IP_FRAG_USES_STATIC_BUF - /* When using a static buffer, we use a PBUF_REF, which we will - * use to reference the packet (without link header). - * Layer and length is irrelevant. - */ - rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); - if (rambuf == NULL) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); - goto memerr; - } - rambuf->tot_len = rambuf->len = mtu; - rambuf->payload = LWIP_MEM_ALIGN((void *)buf); - - /* Copy the IP header in it */ - iphdr = (struct ip_hdr *)rambuf->payload; - SMEMCPY(iphdr, p->payload, IP_HLEN); -#else /* IP_FRAG_USES_STATIC_BUF */ original_iphdr = (struct ip_hdr *)p->payload; iphdr = original_iphdr; -#endif /* IP_FRAG_USES_STATIC_BUF */ + LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); /* Save original offset */ - tmp = ntohs(IPH_OFFSET(iphdr)); + tmp = lwip_ntohs(IPH_OFFSET(iphdr)); ofo = tmp & IP_OFFMASK; - omf = tmp & IP_MF; + LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); left = p->tot_len - IP_HLEN; - nfb = (mtu - IP_HLEN) / 8; - while (left) { - last = (left <= mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = omf | (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - /* Fill this fragment */ - cop = last ? left : nfb * 8; + fragsize = LWIP_MIN(left, nfb * 8); -#if IP_FRAG_USES_STATIC_BUF - poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); -#else /* IP_FRAG_USES_STATIC_BUF */ #if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); if (rambuf == NULL) { goto memerr; } LWIP_ASSERT("this needs a pbuf in one piece!", (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); /* make room for the IP header */ if (pbuf_header(rambuf, IP_HLEN)) { pbuf_free(rambuf); @@ -790,16 +747,14 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); iphdr = (struct ip_hdr *)rambuf->payload; - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - - left_to_copy = cop; + left_to_copy = fragsize; while (left_to_copy) { struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + u16_t plen = p->len - poff; + newpbuflen = LWIP_MIN(left_to_copy, plen); /* Is this pbuf already empty? */ if (!newpbuflen) { + poff = 0; p = p->next; continue; } @@ -809,7 +764,8 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) goto memerr; } /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, + (u8_t*)p->payload + poff, newpbuflen); if (newpbuf == NULL) { ip_frag_free_pbuf_custom_ref(pcr); pbuf_free(rambuf); @@ -825,16 +781,23 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) pbuf_cat(rambuf, newpbuf); left_to_copy -= newpbuflen; if (left_to_copy) { + poff = 0; p = p->next; } } - poff = newpbuflen; + poff += newpbuflen; #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ /* Correct header */ - IPH_OFFSET_SET(iphdr, htons(tmp)); - IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + last = (left <= netif->mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); + IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); IPH_CHKSUM_SET(iphdr, 0); #if CHECKSUM_GEN_IP IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { @@ -842,29 +805,6 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) } #endif /* CHECKSUM_GEN_IP */ -#if IP_FRAG_USES_STATIC_BUF - if (last) { - pbuf_realloc(rambuf, left + IP_HLEN); - } - - /* This part is ugly: we alloc a RAM based pbuf for - * the link level header for each chunk and then - * free it. A PBUF_ROM style pbuf for which pbuf_header - * worked would make things simpler. - */ - header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); - if (header != NULL) { - pbuf_chain(header, rambuf); - netif->output(netif, header, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - MIB2_STATS_INC(mib2.ipfragcreates); - pbuf_free(header); - } else { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); - pbuf_free(rambuf); - goto memerr; - } -#else /* IP_FRAG_USES_STATIC_BUF */ /* No need for separate header pbuf - we allowed room for it in rambuf * when allocated. */ @@ -879,13 +819,9 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) */ pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ - left -= cop; + left -= fragsize; ofo += nfb; } -#if IP_FRAG_USES_STATIC_BUF - pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ MIB2_STATS_INC(mib2.ipfragoks); return ERR_OK; memerr: diff --git a/src/core/ipv6/README b/src/core/ipv6/README deleted file mode 100644 index 36200048..00000000 --- a/src/core/ipv6/README +++ /dev/null @@ -1 +0,0 @@ -IPv6 support in lwIP is very experimental. diff --git a/src/core/ipv6/ethip6.c b/src/core/ipv6/ethip6.c index 81a19955..509fc1c5 100644 --- a/src/core/ipv6/ethip6.c +++ b/src/core/ipv6/ethip6.c @@ -51,35 +51,11 @@ #include "lwip/inet_chksum.h" #include "lwip/netif.h" #include "lwip/icmp6.h" +#include "lwip/prot/ethernet.h" #include "netif/ethernet.h" #include -/** - * Send an IPv6 packet on the network using netif->linkoutput - * The ethernet header is filled in before sending. - * - * @params netif the lwIP network interface on which to send the packet - * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header - * @params src the source MAC address to be copied into the ethernet header - * @params dst the destination MAC address to be copied into the ethernet header - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -static err_t -ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) -{ - struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; - - LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!", - (netif->hwaddr_len == 6)); - SMEMCPY(ðhdr->dest, dst, 6); - SMEMCPY(ðhdr->src, src, 6); - ethhdr->type = PP_HTONS(ETHTYPE_IPV6); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p)); - /* send the packet */ - return netif->linkoutput(netif, p); -} - /** * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. * @@ -96,7 +72,7 @@ ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct et * * @return * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or etharp_send_ip(). + * or the return type of either nd6_queue_packet() or ethernet_output(). */ err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) @@ -104,14 +80,6 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) struct eth_addr dest; s8_t i; - /* make room for Ethernet header - should not fail */ - if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { - /* bail out */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_output: could not allocate room for header.\n")); - return ERR_BUF; - } - /* multicast destination IP address? */ if (ip6_addr_ismulticast(ip6addr)) { /* Hash IP multicast address to MAC address.*/ @@ -123,7 +91,7 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; /* Send out. */ - return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); } /* We have a unicast destination IP address */ @@ -139,7 +107,7 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) if (neighbor_cache[i].state == ND6_STALE) { /* Switch to delay state. */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ if ((neighbor_cache[i].state == ND6_REACHABLE) || @@ -148,11 +116,10 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) /* Send out. */ SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6); - return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); } /* We should queue packet on this interface. */ - pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR); return nd6_queue_packet(i, q); } diff --git a/src/core/ipv6/icmp6.c b/src/core/ipv6/icmp6.c index 397d2d6b..323b69a2 100644 --- a/src/core/ipv6/icmp6.c +++ b/src/core/ipv6/icmp6.c @@ -44,6 +44,7 @@ #if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ #include "lwip/icmp6.h" +#include "lwip/prot/icmp6.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" #include "lwip/inet_chksum.h" @@ -80,8 +81,8 @@ void icmp6_input(struct pbuf *p, struct netif *inp) { struct icmp6_hdr *icmp6hdr; - struct pbuf * r; - const ip6_addr_t * reply_src; + struct pbuf *r; + const ip6_addr_t *reply_src; ICMP6_STATS_INC(icmp6.recv); diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index 3f604dfd..8cc9c010 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -46,6 +46,7 @@ #include "lwip/def.h" #include "lwip/mem.h" #include "lwip/netif.h" +#include "lwip/ip.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" #include "lwip/ip6_frag.h" @@ -192,6 +193,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } /** + * @ingroup ip6 * Select the best IPv6 source address for a given destination * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior * is assumed. @@ -202,7 +204,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) * source address is found */ const ip_addr_t * -ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest) +ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) { const ip_addr_t *src = NULL; u8_t i; @@ -451,7 +453,7 @@ ip6_input(struct pbuf *p, struct netif *inp) IP6_STATS_INC(ip6.drop); return ERR_OK; } - + /* current header pointer. */ ip_data.current_ip6_header = ip6hdr; @@ -641,7 +643,7 @@ netif_found: case IP6_NEXTH_FRAGMENT: { - struct ip6_frag_hdr * frag_hdr; + struct ip6_frag_hdr *frag_hdr; LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); frag_hdr = (struct ip6_frag_hdr *)p->payload; @@ -781,11 +783,11 @@ ip6_input_cleanup: * used as source (usually during network startup). If the source IPv6 address it * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network * interface is filled in as source address. If the destination IPv6 address is - * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points - * to it instead of the data. + * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and + * p->payload points to it instead of the data. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an IPv6 header and p->payload points to that IPv6 header) * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an * IP address of the netif is selected and used as source address. @@ -805,7 +807,7 @@ ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, u8_t nexth, struct netif *netif) { const ip6_addr_t *src_used = src; - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { if (src != NULL && ip6_addr_isany(src)) { src = ip_2_ip6(ip6_select_source_address(netif, dest)); if ((src == NULL) || ip6_addr_isany(src)) { @@ -834,7 +836,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); /* Should the IPv6 header be generated or is it already included in p? */ - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { /* generate IPv6 header */ if (pbuf_header(p, IP6_HLEN)) { LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); @@ -907,7 +909,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, * interface and calls upon ip6_output_if to do the actual work. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an IPv6 header and p->payload points to that IPv6 header) * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an * IP address of the netif is selected and used as source address. @@ -930,7 +932,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { netif = ip6_route(src, dest); } else { /* IP header included in p, read addresses. */ @@ -963,7 +965,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, * before calling ip6_output_if. * * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an IPv6 header and p->payload points to that IPv6 header) * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an * IP address of the netif is selected and used as source address. @@ -989,7 +991,7 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - if (dest != IP_HDRINCL) { + if (dest != LWIP_IP_HDRINCL) { netif = ip6_route(src, dest); } else { /* IP header included in p, read addresses. */ @@ -1033,9 +1035,9 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise */ err_t -ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value) +ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) { - struct ip6_hbh_hdr * hbh_hdr; + struct ip6_hbh_hdr *hbh_hdr; /* Move pointer to make room for hop-by-hop options header. */ if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c index 7f14db44..964291ee 100644 --- a/src/core/ipv6/ip6_addr.c +++ b/src/core/ipv6/ip6_addr.c @@ -73,7 +73,7 @@ int ip6addr_aton(const char *cp, ip6_addr_t *addr) { u32_t addr_index, zero_blocks, current_block_index, current_block_value; - const char * s; + const char *s; /* Count the number of colons, to count the number of blocks in a "::" sequence zero_blocks may be 1 even if there are no :: sequences */ @@ -152,7 +152,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) /* convert to network byte order. */ if (addr) { for (addr_index = 0; addr_index < 4; addr_index++) { - addr->addr[addr_index] = htonl(addr->addr[addr_index]); + addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); } } @@ -199,7 +199,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) for (current_block_index = 0; current_block_index < 8; current_block_index++) { /* get the current 16-bit block */ - current_block_value = htonl(addr->addr[current_block_index >> 1]); + current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); if ((current_block_index & 0x1) == 0) { current_block_value = current_block_value >> 16; } @@ -218,7 +218,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) if (empty_block_flag == 0) { /* generate empty block "::", but only if more than one contiguous zero block, * according to current formatting suggestions RFC 5952. */ - next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); if ((current_block_index & 0x1) == 0x01) { next_block_value = next_block_value >> 16; } diff --git a/src/core/ipv6/ip6_frag.c b/src/core/ipv6/ip6_frag.c index f574d380..b374f691 100644 --- a/src/core/ipv6/ip6_frag.c +++ b/src/core/ipv6/ip6_frag.c @@ -147,7 +147,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) { struct ip6_reassdata *prev; u16_t pbufs_freed = 0; - u8_t clen; + u16_t clen; struct pbuf *p; struct ip6_reass_helper *iprh; @@ -260,9 +260,10 @@ ip6_reass(struct pbuf *p) { struct ip6_reassdata *ipr, *ipr_prev; struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct ip6_frag_hdr * frag_hdr; + struct ip6_frag_hdr *frag_hdr; u16_t offset, len; - u8_t clen, valid = 1; + u16_t clen; + u8_t valid = 1; struct pbuf *q; IP6_FRAG_STATS_INC(ip6_frag.recv); @@ -278,12 +279,12 @@ ip6_reass(struct pbuf *p) clen = pbuf_clen(p); - offset = ntohs(frag_hdr->_fragment_offset); + offset = lwip_ntohs(frag_hdr->_fragment_offset); /* Calculate fragment length from IPv6 payload length. * Adjust for headers before Fragment Header. * And finally adjust by Fragment Header length. */ - len = ntohs(ip6_current_header()->_plen); + len = lwip_ntohs(ip6_current_header()->_plen); len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); len -= IP6_FRAG_HLEN; @@ -377,8 +378,8 @@ ip6_reass(struct pbuf *p) if (IPV6_FRAG_REQROOM > 0) { /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). This cannot fail since we already checked when receiving this fragment. */ - err_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } #else /* IPV6_FRAG_COPYHEADER */ LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", @@ -528,8 +529,8 @@ ip6_reass(struct pbuf *p) #if IPV6_FRAG_COPYHEADER if (IPV6_FRAG_REQROOM > 0) { /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ - err_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } #endif pbuf_cat(ipr->p, next_pbuf); @@ -544,8 +545,8 @@ ip6_reass(struct pbuf *p) #if IPV6_FRAG_COPYHEADER if (IPV6_FRAG_REQROOM > 0) { /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ - err_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); @@ -559,7 +560,7 @@ ip6_reass(struct pbuf *p) - IP6_HLEN); /* Set payload length in ip header. */ - iphdr_ptr->_plen = htons(ipr->datagram_len); + iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); /* Get the first pbuf. */ p = ipr->p; @@ -655,7 +656,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) { struct ip6_hdr *original_ip6hdr; struct ip6_hdr *ip6hdr; - struct ip6_frag_hdr * frag_hdr; + struct ip6_frag_hdr *frag_hdr; struct pbuf *rambuf; struct pbuf *newpbuf; static u32_t identification; @@ -696,7 +697,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) return ERR_MEM; } LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); + (p->len >= (IP6_HLEN))); SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); ip6hdr = (struct ip6_hdr *)rambuf->payload; frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); @@ -747,8 +748,8 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) /* Set headers */ frag_hdr->_nexth = original_ip6hdr->_nexth; frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); - frag_hdr->_identification = htonl(identification); + frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = lwip_htonl(identification); IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c index ef854e76..0cd0078b 100644 --- a/src/core/ipv6/mld6.c +++ b/src/core/ipv6/mld6.c @@ -1,5 +1,12 @@ /** * @file + * Multicast listener discovery + * + * @defgroup mld6 MLD6 + * @ingroup ip6 + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2.\n + * To be called from TCPIP thread */ /* @@ -37,14 +44,6 @@ * */ -/** - * @defgroup mld6 MLD6 - * @ingroup ip6 - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2.\n - * To be called from TCPIP thread - */ - /* Based on igmp.c implementation of igmp v2 protocol */ #include "lwip/opt.h" @@ -52,6 +51,7 @@ #if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ #include "lwip/mld6.h" +#include "lwip/prot/mld6.h" #include "lwip/icmp6.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" @@ -75,16 +75,11 @@ #define MLD6_GROUP_DELAYING_MEMBER 1 #define MLD6_GROUP_IDLE_MEMBER 2 - -/* The list of joined groups. */ -static struct mld_group* mld_group_list; - - /* Forward declarations. */ -static struct mld_group * mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); -static err_t mld6_free_group(struct mld_group *group); +static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); +static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); -static void mld6_send(struct mld_group *group, u8_t type); +static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); /** @@ -95,33 +90,21 @@ static void mld6_send(struct mld_group *group, u8_t type); err_t mld6_stop(struct netif *netif) { - struct mld_group *group = mld_group_list; - struct mld_group *prev = NULL; - struct mld_group *next; + struct mld_group *group = netif_mld6_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); - /* look for groups joined on this interface further down the list */ while (group != NULL) { - next = group->next; - /* is it a group joined on this interface? */ - if (group->netif == netif) { - /* is it the first group of the list? */ - if (group == mld_group_list) { - mld_group_list = next; - } - /* is there a "previous" group defined? */ - if (prev != NULL) { - prev->next = next; - } - /* disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER); - } - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - } else { - /* change the "previous" */ - prev = group; + struct mld_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); } + + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + /* move to "next" */ group = next; } @@ -136,12 +119,10 @@ mld6_stop(struct netif *netif) void mld6_report_groups(struct netif *netif) { - struct mld_group *group = mld_group_list; + struct mld_group *group = netif_mld6_data(netif); while (group != NULL) { - if (group->netif == netif) { - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); group = group->next; } } @@ -157,10 +138,10 @@ mld6_report_groups(struct netif *netif) struct mld_group * mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) { - struct mld_group *group = mld_group_list; + struct mld_group *group = netif_mld6_data(ifp); while (group != NULL) { - if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) { + if (ip6_addr_cmp(&(group->group_address), addr)) { return group; } group = group->next; @@ -185,38 +166,37 @@ mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); if (group != NULL) { - group->netif = ifp; ip6_addr_set(&(group->group_address), addr); group->timer = 0; /* Not running */ group->group_state = MLD6_GROUP_IDLE_MEMBER; group->last_reporter_flag = 0; group->use = 0; - group->next = mld_group_list; + group->next = netif_mld6_data(ifp); - mld_group_list = group; + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); } return group; } /** - * Remove a group in the mld_group_list and free + * Remove a group from the mld_group_list, but do not free it yet * * @param group the group to remove * @return ERR_OK if group was removed from the list, an err_t otherwise */ static err_t -mld6_free_group(struct mld_group *group) +mld6_remove_group(struct netif *netif, struct mld_group *group) { err_t err = ERR_OK; /* Is it the first group? */ - if (mld_group_list == group) { - mld_group_list = group->next; + if (netif_mld6_data(netif) == group) { + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next); } else { /* look for group further down the list */ struct mld_group *tmpGroup; - for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { if (tmpGroup->next == group) { tmpGroup->next = group->next; break; @@ -227,8 +207,6 @@ mld6_free_group(struct mld_group *group) err = ERR_ARG; } } - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); return err; } @@ -243,8 +221,8 @@ mld6_free_group(struct mld_group *group) void mld6_input(struct pbuf *p, struct netif *inp) { - struct mld_header * mld_hdr; - struct mld_group* group; + struct mld_header *mld_hdr; + struct mld_group *group; MLD6_STATS_INC(mld6.recv); @@ -266,10 +244,9 @@ mld6_input(struct pbuf *p, struct netif *inp) ip6_addr_isany(&(mld_hdr->multicast_address))) { MLD6_STATS_INC(mld6.rx_general); /* Report all groups, except all nodes group, and if-local groups. */ - group = mld_group_list; + group = netif_mld6_data(inp); while (group != NULL) { - if ((group->netif == inp) && - (!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { mld6_delayed_report(group, mld_hdr->max_resp_delay); } @@ -373,12 +350,12 @@ mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) /* Activate this address on the MAC layer. */ if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); + netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); } /* Report our membership. */ MLD6_STATS_INC(mld6.tx_report); - mld6_send(group, ICMP6_TYPE_MLR); + mld6_send(netif, group, ICMP6_TYPE_MLR); mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); } @@ -440,19 +417,22 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) if (group != NULL) { /* Leave if there is no other use of the group */ if (group->use <= 1) { + /* Remove the group from the list */ + mld6_remove_group(netif, group); + /* If we are the last reporter for this group */ if (group->last_reporter_flag) { MLD6_STATS_INC(mld6.tx_leave); - mld6_send(group, ICMP6_TYPE_MLD); + mld6_send(netif, group, ICMP6_TYPE_MLD); } /* Disable the group at the MAC level */ if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); + netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); } - /* Free the group */ - mld6_free_group(group); + /* free group struct */ + memp_free(MEMP_MLD6_GROUP, group); } else { /* Decrement group use */ group->use--; @@ -476,21 +456,26 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) void mld6_tmr(void) { - struct mld_group *group = mld_group_list; + struct netif *netif = netif_list; - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - MLD6_STATS_INC(mld6.tx_report); - mld6_send(group, ICMP6_TYPE_MLR); - group->group_state = MLD6_GROUP_IDLE_MEMBER; + while (netif != NULL) { + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } } } + group = group->next; } - group = group->next; + netif = netif->next; } } @@ -537,11 +522,11 @@ mld6_delayed_report(struct mld_group *group, u16_t maxresp) * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) */ static void -mld6_send(struct mld_group *group, u8_t type) +mld6_send(struct netif *netif, struct mld_group *group, u8_t type) { - struct mld_header * mld_hdr; - struct pbuf * p; - const ip6_addr_t * src_addr; + struct mld_header *mld_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); @@ -558,13 +543,13 @@ mld6_send(struct mld_group *group, u8_t type) } /* Select our source address. */ - if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) { + if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { /* This is a special case, when we are performing duplicate address detection. * We must join the multicast group, but we don't have a valid address yet. */ src_addr = IP6_ADDR_ANY6; } else { /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(group->netif, 0); + src_addr = netif_ip6_addr(netif, 0); } /* MLD message header pointer. */ @@ -579,7 +564,7 @@ mld6_send(struct mld_group *group, u8_t type) ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); #if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) { + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, &(group->group_address)); } @@ -591,7 +576,7 @@ mld6_send(struct mld_group *group, u8_t type) /* Send the packet out. */ MLD6_STATS_INC(mld6.xmit); ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), - MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif); + MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); pbuf_free(p); } diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index af17aeaf..82394f6e 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -46,6 +46,8 @@ #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ #include "lwip/nd6.h" +#include "lwip/prot/nd6.h" +#include "lwip/prot/icmp6.h" #include "lwip/pbuf.h" #include "lwip/mem.h" #include "lwip/memp.h" @@ -60,6 +62,9 @@ #include +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#endif /* Router tables. */ struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; @@ -82,23 +87,24 @@ static ip6_addr_t multicast_address; static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; /* Forward declarations. */ -static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr); +static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); static s8_t nd6_new_neighbor_cache_entry(void); static void nd6_free_neighbor_cache_entry(s8_t i); -static s8_t nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr); +static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); static s8_t nd6_new_destination_cache_entry(void); -static s8_t nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif); -static s8_t nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif); -static s8_t nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif); -static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); -static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); +static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); #define ND6_SEND_FLAG_MULTICAST_DEST 0x01 #define ND6_SEND_FLAG_ALLNODES_DEST 0x02 -static void nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags); -static void nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags); +static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); #if LWIP_IPV6_SEND_ROUTER_SOLICIT -static err_t nd6_send_rs(struct netif * netif); +static err_t nd6_send_rs(struct netif *netif); #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ #if LWIP_ND6_QUEUEING @@ -127,8 +133,8 @@ nd6_input(struct pbuf *p, struct netif *inp) switch (msg_type) { case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ { - struct na_header * na_hdr; - struct lladdr_option * lladdr_opt; + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; /* Check that na header fits in packet. */ if (p->len < (sizeof(struct na_header))) { @@ -143,6 +149,8 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Unsolicited NA?*/ if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + ip6_addr_t target_address; + /* This is an unsolicited NA. * link-layer changed? * part of DAD mechanism? */ @@ -166,27 +174,27 @@ nd6_input(struct pbuf *p, struct netif *inp) return; } - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* If the target address matches this netif, it is a DAD response. */ for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { /* We are using a duplicate address. */ netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); #if LWIP_IPV6_MLD /* Leave solicited node multicast group. */ ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); - mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); + mld6_leavegroup_netif(inp, &multicast_address); #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_AUTOCONFIG /* Check to see if this address was autoconfigured. */ - if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { - i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (!ip6_addr_islinklocal(&target_address)) { + i = nd6_get_onlink_prefix(&target_address, inp); if (i >= 0) { /* Mark this prefix as duplicate, so that we don't use it * to generate this address again. */ @@ -202,22 +210,24 @@ nd6_input(struct pbuf *p, struct netif *inp) #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ /* This is an unsolicited NA, most likely there was a LLADDR change. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + i = nd6_find_neighbor_cache_entry(&target_address); if (i >= 0) { if (na_hdr->flags & ND6_FLAG_OVERRIDE) { MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); } } } else { + ip6_addr_t target_address; + /* This is a solicited NA. * neighbor address resolution response? * neighbor unreachability detection response? */ - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); /* Find the cache entry corresponding to this na. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + i = nd6_find_neighbor_cache_entry(&target_address); if (i < 0) { /* We no longer care about this target address. drop it. */ pbuf_free(p); @@ -225,8 +235,6 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Update cache entry. */ - neighbor_cache[i].netif = inp; - neighbor_cache[i].counter.reachable_time = reachable_time; if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || (neighbor_cache[i].state == ND6_INCOMPLETE)) { /* Check that link-layer address option also fits in packet. */ @@ -250,7 +258,10 @@ nd6_input(struct pbuf *p, struct netif *inp) MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); } + + neighbor_cache[i].netif = inp; neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; /* Send queued packets, if any. */ if (neighbor_cache[i].q != NULL) { @@ -262,8 +273,8 @@ nd6_input(struct pbuf *p, struct netif *inp) } case ICMP6_TYPE_NS: /* Neighbor solicitation. */ { - struct ns_header * ns_hdr; - struct lladdr_option * lladdr_opt; + struct ns_header *ns_hdr; + struct lladdr_option *lladdr_opt; u8_t accepted; /* Check that ns header fits in packet. */ @@ -320,6 +331,8 @@ nd6_input(struct pbuf *p, struct netif *inp) } } } else { + ip6_addr_t target_address; + /* Sender is trying to resolve our address. */ /* Verify that they included their own link-layer address. */ if (lladdr_opt == NULL) { @@ -339,7 +352,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } else { /* Add their IPv6 address and link-layer address to neighbor cache. @@ -360,22 +373,22 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(ns_hdr->target_address)); /* Send back a NA for us. Allocate the reply pbuf. */ - nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); } break; /* ICMP6_TYPE_NS */ } case ICMP6_TYPE_RA: /* Router Advertisement. */ { - struct ra_header * ra_hdr; - u8_t * buffer; /* Used to copy options. */ + struct ra_header *ra_hdr; + u8_t *buffer; /* Used to copy options. */ u16_t offset; /* Check that RA header fits in packet. */ @@ -413,15 +426,15 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Re-set invalidation timer. */ - default_router_list[i].invalidation_timer = htons(ra_hdr->router_lifetime); + default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); /* Re-set default timer values. */ #if LWIP_ND6_ALLOW_RA_UPDATES if (ra_hdr->retrans_timer > 0) { - retrans_timer = htonl(ra_hdr->retrans_timer); + retrans_timer = lwip_htonl(ra_hdr->retrans_timer); } if (ra_hdr->reachable_time > 0) { - reachable_time = htonl(ra_hdr->reachable_time); + reachable_time = lwip_htonl(ra_hdr->reachable_time); } #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ @@ -441,7 +454,12 @@ nd6_input(struct pbuf *p, struct netif *inp) buffer = &((u8_t*)p->payload)[offset]; } else { buffer = nd6_ra_buffer; - pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset); + if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } } if (buffer[1] == 0) { /* zero-length extension. drop packet */ @@ -453,7 +471,7 @@ nd6_input(struct pbuf *p, struct netif *inp) switch (buffer[0]) { case ND6_OPTION_TYPE_SOURCE_LLADDR: { - struct lladdr_option * lladdr_opt; + struct lladdr_option *lladdr_opt; lladdr_opt = (struct lladdr_option *)buffer; if ((default_router_list[i].neighbor_entry != NULL) && (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { @@ -465,35 +483,38 @@ nd6_input(struct pbuf *p, struct netif *inp) } case ND6_OPTION_TYPE_MTU: { - struct mtu_option * mtu_opt; + struct mtu_option *mtu_opt; mtu_opt = (struct mtu_option *)buffer; - if (htonl(mtu_opt->mtu) >= 1280) { + if (lwip_htonl(mtu_opt->mtu) >= 1280) { #if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = (u16_t)htonl(mtu_opt->mtu); + inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ } break; } case ND6_OPTION_TYPE_PREFIX_INFO: { - struct prefix_option * prefix_opt; + struct prefix_option *prefix_opt; prefix_opt = (struct prefix_option *)buffer; - if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) { + if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && + (prefix_opt->prefix_length == 64) && + !ip6_addr_islinklocal(&(prefix_opt->prefix))) { /* Add to on-link prefix list. */ s8_t prefix; + ip6_addr_t prefix_addr; /* Get a memory-aligned copy of the prefix. */ - ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); + ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); /* find cache entry for this prefix. */ - prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + prefix = nd6_get_onlink_prefix(&prefix_addr, inp); if (prefix < 0) { /* Create a new cache entry. */ - prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); + prefix = nd6_new_onlink_prefix(&prefix_addr, inp); } if (prefix >= 0) { - prefix_list[prefix].invalidation_timer = htonl(prefix_opt->valid_lifetime); + prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); #if LWIP_IPV6_AUTOCONFIG if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { @@ -526,8 +547,8 @@ nd6_input(struct pbuf *p, struct netif *inp) } case ICMP6_TYPE_RD: /* Redirect */ { - struct redirect_header * redir_hdr; - struct lladdr_option * lladdr_opt; + struct redirect_header *redir_hdr; + struct lladdr_option *lladdr_opt; /* Check that Redir header fits in packet. */ if (p->len < sizeof(struct redirect_header)) { @@ -580,7 +601,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } if (i >= 0) { @@ -589,7 +610,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } } @@ -599,7 +620,7 @@ nd6_input(struct pbuf *p, struct netif *inp) case ICMP6_TYPE_PTB: /* Packet too big */ { struct icmp6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ u32_t pmtu; /* Check that ICMPv6 header + IPv6 header fit in payload */ @@ -626,7 +647,7 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Change the Path MTU. */ - pmtu = htonl(icmp6hdr->data); + pmtu = lwip_htonl(icmp6hdr->data); destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); break; /* ICMP6_TYPE_PTB */ @@ -655,7 +676,7 @@ void nd6_tmr(void) { s8_t i; - struct netif * netif; + struct netif *netif; /* Process neighbor entries. */ for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { @@ -668,7 +689,7 @@ nd6_tmr(void) } else { /* Send a NS for this entry. */ neighbor_cache[i].counter.probes_sent++; - nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST); + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); } break; case ND6_REACHABLE: @@ -685,15 +706,15 @@ nd6_tmr(void) } break; case ND6_STALE: - neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; + neighbor_cache[i].counter.stale_time++; break; case ND6_DELAY: - if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { + if (neighbor_cache[i].counter.delay_time <= 1) { /* Change to PROBE state. */ neighbor_cache[i].state = ND6_PROBE; neighbor_cache[i].counter.probes_sent = 0; } else { - neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; + neighbor_cache[i].counter.delay_time--; } break; case ND6_PROBE: @@ -704,7 +725,7 @@ nd6_tmr(void) } else { /* Send a NS for this entry. */ neighbor_cache[i].counter.probes_sent++; - nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0); + nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); } break; case ND6_NO_ENTRY: @@ -738,15 +759,14 @@ nd6_tmr(void) /* Process prefix entries. */ for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].netif != NULL) { + if (prefix_list[i].netif != NULL) { if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { /* Entry timed out, remove it */ prefix_list[i].invalidation_timer = 0; #if LWIP_IPV6_AUTOCONFIG /* If any addresses were configured with this prefix, remove them */ - if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) - { + if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { s8_t j; for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { @@ -778,7 +798,7 @@ nd6_tmr(void) for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { /* Generate an address using this prefix and interface ID from link-local address. */ - IP_ADDR6(&prefix_list[i].netif->ip6_addr[j], + netif_ip6_addr_set_parts(prefix_list[i].netif, j, prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); @@ -795,29 +815,31 @@ nd6_tmr(void) } #endif /* LWIP_IPV6_AUTOCONFIG */ } - } + } } /* Process our own addresses, if DAD configured. */ for (netif = netif_list; netif != NULL; netif = netif->next) { for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_istentative(netif->ip6_addr_state[i])) { - if ((netif->ip6_addr_state[i] & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + u8_t addr_state = netif_ip6_addr_state(netif, i); + if (ip6_addr_istentative(addr_state)) { + if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { /* No NA received in response. Mark address as valid. */ - netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED; + netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); /* @todo implement preferred and valid lifetimes. */ } else if (netif->flags & NETIF_FLAG_UP) { #if LWIP_IPV6_MLD - if ((netif->ip6_addr_state[i] & 0x07) == 0) { + if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) == 0) { /* Join solicited node multicast group. */ ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); - mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); + mld6_joingroup_netif(netif, &multicast_address); } #endif /* LWIP_IPV6_MLD */ /* Send a NS for this address. */ nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); - netif->ip6_addr_state[i]++; + /* tentative: set next state by increasing by one */ + netif_ip6_addr_set_state(netif, i, addr_state + 1); /* @todo send max 1 NS per tmr call? enable return*/ /*return;*/ } @@ -839,6 +861,17 @@ nd6_tmr(void) } +/** Send a neighbor solicitation message for a specific neighbor cache entry + * + * @param entry the neightbor cache entry for wich to send the message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) +{ + nd6_send_ns(entry->netif, &entry->next_hop_address, flags); +} + /** * Send a neighbor solicitation message * @@ -847,11 +880,11 @@ nd6_tmr(void) * @param flags one of ND6_SEND_FLAG_* */ static void -nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) +nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) { - struct ns_header * ns_hdr; - struct pbuf * p; - const ip6_addr_t * src_addr; + struct ns_header *ns_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; u16_t lladdr_opt_len; if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { @@ -916,17 +949,17 @@ nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) * @param flags one of ND6_SEND_FLAG_* */ static void -nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) +nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) { - struct na_header * na_hdr; - struct lladdr_option * lladdr_opt; - struct pbuf * p; - const ip6_addr_t * src_addr; - const ip6_addr_t * dest_addr; + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; + const ip6_addr_t *dest_addr; u16_t lladdr_opt_len; /* Use link-local address as source address. */ - /* src_addr = &(netif->ip6_addr[0]); */ + /* src_addr = netif_ip6_addr(netif, 0); */ /* Use target address as source address. */ src_addr = target_addr; @@ -987,12 +1020,12 @@ nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) * @param netif the netif on which to send the message */ static err_t -nd6_send_rs(struct netif * netif) +nd6_send_rs(struct netif *netif) { - struct rs_header * rs_hdr; - struct lladdr_option * lladdr_opt; - struct pbuf * p; - const ip6_addr_t * src_addr; + struct rs_header *rs_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; err_t err; u16_t lladdr_opt_len = 0; @@ -1058,7 +1091,7 @@ nd6_send_rs(struct netif * netif) * entry is found */ static s8_t -nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr) +nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) { s8_t i; for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { @@ -1217,7 +1250,7 @@ nd6_free_neighbor_cache_entry(s8_t i) * entry is found */ static s8_t -nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr) +nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) { s8_t i; for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { @@ -1267,7 +1300,7 @@ nd6_new_destination_cache_entry(void) * @return 1 if the address is on-link, 0 otherwise */ static s8_t -nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif) +nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { @@ -1296,7 +1329,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif) * router is found */ s8_t -nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif) +nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; /* last_router is used for round-robin router selection (as recommended @@ -1355,7 +1388,7 @@ nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif) * @return the index of the router entry, or -1 if not found */ static s8_t -nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif) +nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) { s8_t i; @@ -1380,7 +1413,7 @@ nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif) * @return the index on the router table, or -1 if could not be created */ static s8_t -nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif) +nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) { s8_t router_index; s8_t neighbor_index; @@ -1398,7 +1431,8 @@ nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif) neighbor_cache[neighbor_index].netif = netif; neighbor_cache[neighbor_index].q = NULL; neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; - neighbor_cache[neighbor_index].counter.probes_sent = 0; + neighbor_cache[neighbor_index].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); } /* Mark neighbor as router. */ @@ -1429,7 +1463,7 @@ nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif) * @return the index on the prefix table, or -1 if not found */ static s8_t -nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) { s8_t i; @@ -1453,7 +1487,7 @@ nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) * @return the index on the prefix table, or -1 if not created */ static s8_t -nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) { s8_t i; @@ -1488,7 +1522,7 @@ nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) * could be created */ s8_t -nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif) +nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; @@ -1582,7 +1616,8 @@ nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif) neighbor_cache[i].isrouter = 0; neighbor_cache[i].netif = netif; neighbor_cache[i].state = ND6_INCOMPLETE; - neighbor_cache[i].counter.probes_sent = 0; + neighbor_cache[i].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); } } @@ -1600,7 +1635,7 @@ nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif) * @return ERR_OK if succeeded, ERR_MEM if out of memory */ err_t -nd6_queue_packet(s8_t neighbor_index, struct pbuf * q) +nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) { err_t result = ERR_MEM; struct pbuf *p; @@ -1735,6 +1770,7 @@ static void nd6_send_q(s8_t i) { struct ip6_hdr *ip6hdr; + ip6_addr_t dest; #if LWIP_ND6_QUEUEING struct nd6_q_entry *q; #endif /* LWIP_ND6_QUEUEING */ @@ -1751,10 +1787,10 @@ nd6_send_q(s8_t i) neighbor_cache[i].q = q->next; /* Get ipv6 header. */ ip6hdr = (struct ip6_hdr *)(q->p->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); /* free the queued IP packet */ pbuf_free(q->p); /* now queue entry can be freed */ @@ -1764,10 +1800,10 @@ nd6_send_q(s8_t i) if (neighbor_cache[i].q != NULL) { /* Get ipv6 header. */ ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); /* free the queued IP packet */ pbuf_free(neighbor_cache[i].q); neighbor_cache[i].q = NULL; @@ -1784,7 +1820,7 @@ nd6_send_q(s8_t i) * @return the Path MTU, if known, or the netif default MTU */ u16_t -nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif) +nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; @@ -1814,7 +1850,7 @@ nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif) * by an upper layer protocol (TCP) */ void -nd6_reachability_hint(const ip6_addr_t * ip6addr) +nd6_reachability_hint(const ip6_addr_t *ip6addr) { s8_t i; @@ -1857,7 +1893,7 @@ nd6_reachability_hint(const ip6_addr_t * ip6addr) * @param netif points to a network interface */ void -nd6_cleanup_netif(struct netif * netif) +nd6_cleanup_netif(struct netif *netif) { u8_t i; s8_t router_index; diff --git a/src/core/mem.c b/src/core/mem.c index 070d103a..40f4cb9e 100644 --- a/src/core/mem.c +++ b/src/core/mem.c @@ -9,7 +9,7 @@ * * To let mem_malloc() use pools (prevents fragmentation and is much faster than * a heap but might waste some memory), define MEM_USE_POOLS to 1, define - * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list * of pools like this (more pools can be added between _START and _END): * * Define three pools with sizes 256, 512, and 1512 bytes @@ -54,13 +54,14 @@ */ #include "lwip/opt.h" -#include "lwip/def.h" #include "lwip/mem.h" +#include "lwip/def.h" #include "lwip/sys.h" #include "lwip/stats.h" #include "lwip/err.h" #include +#include #if MEM_LIBC_MALLOC || MEM_USE_POOLS /** mem_init is not used when using pools instead of a heap or using @@ -166,12 +167,21 @@ mem_malloc(mem_size_t size) mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { -#if MEM_USE_POOLS_TRY_BIGGER_POOL -again: -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ /* is this pool big enough to hold an element of the required size plus a struct memp_malloc_helper that saves the pool this element came from? */ if (required_size <= memp_pools[poolnr]->size) { + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + continue; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + MEM_STATS_INC(err); + return NULL; + } break; } } @@ -180,20 +190,6 @@ again: MEM_STATS_INC(err); return NULL; } - element = (struct memp_malloc_helper*)memp_malloc(poolnr); - if (element == NULL) { - /* No need to DEBUGF or ASSERT: This error is already - taken care of in memp.c */ -#if MEM_USE_POOLS_TRY_BIGGER_POOL - /** Try a bigger pool if this one is empty! */ - if (poolnr < MEMP_POOL_LAST) { - poolnr++; - goto again; - } -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ - MEM_STATS_INC(err); - return NULL; - } /* save the pool number this element came from */ element->poolnr = poolnr; diff --git a/src/core/memp.c b/src/core/memp.c index 5d2c4fb5..2e3db28e 100644 --- a/src/core/memp.c +++ b/src/core/memp.c @@ -4,6 +4,11 @@ * * lwIP has dedicated pools for many structures (netconn, protocol control blocks, * packet buffers, ...). All these pools are managed here. + * + * @defgroup mempool Memory pools + * @ingroup infrastructure + * Custom memory pools + */ /* @@ -38,12 +43,6 @@ * */ -/** - * @defgroup mempool Memory pools - * @ingroup infrastructure - * Custom memory pools - */ - #include "lwip/opt.h" #include "lwip/memp.h" @@ -120,14 +119,14 @@ memp_sanity(const struct memp_desc *desc) * (e.g. the restricted area after it has been altered) * * @param p the memp element to check - * @param memp_type the pool p comes from + * @param desc the pool p comes from */ static void memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) { +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 u16_t k; u8_t *m; -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 m = (u8_t*)p + MEMP_SIZE + desc->size; for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { if (m[k] != 0xcd) { @@ -136,7 +135,10 @@ memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *des LWIP_ASSERT(errstr, 0); } } -#endif +#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ } /** @@ -144,14 +146,14 @@ memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *des * (e.g. the restricted area before it has been altered) * * @param p the memp element to check - * @param memp_type the pool p comes from + * @param desc the pool p comes from */ static void memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 u16_t k; u8_t *m; -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { if (m[k] != 0xcd) { @@ -160,7 +162,10 @@ memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *de LWIP_ASSERT(errstr, 0); } } -#endif +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ } /** @@ -169,6 +174,7 @@ memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *de static void memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 u8_t *m; #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; @@ -178,6 +184,10 @@ memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) m = (u8_t*)p + MEMP_SIZE + desc->size; memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); #endif +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ } #if MEMP_OVERFLOW_CHECK >= 2 @@ -195,7 +205,7 @@ memp_overflow_check_all(void) SYS_ARCH_PROTECT(old_level); for (i = 0; i < MEMP_MAX; ++i) { - p = (struct memp *)(size_t)(memp_pools[i]->base); + p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); for (j = 0; j < memp_pools[i]->num; ++j) { memp_overflow_check_element_overflow(p, memp_pools[i]); memp_overflow_check_element_underflow(p, memp_pools[i]); @@ -205,24 +215,6 @@ memp_overflow_check_all(void) SYS_ARCH_UNPROTECT(old_level); } #endif /* MEMP_OVERFLOW_CHECK >= 2 */ - -#if !MEMP_MEM_MALLOC -/** - * Initialize the restricted areas of all memp elements in a pool. - */ -static void -memp_overflow_init(const struct memp_desc *desc) -{ - u16_t i; - struct memp *p; - - p = (struct memp *)(size_t)(desc->base); - for (i = 0; i < desc->num; ++i) { - memp_overflow_init_element(p, desc); - p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED); - } -} -#endif /* !MEMP_MEM_MALLOC */ #endif /* MEMP_OVERFLOW_CHECK */ /** @@ -246,6 +238,9 @@ memp_init_pool(const struct memp_desc *desc) for (i = 0; i < desc->num; ++i) { memp->next = *desc->tab; *desc->tab = memp; +#if MEMP_OVERFLOW_CHECK + memp_overflow_init_element(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ /* cast through void* to get rid of alignment warnings */ memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size #if MEMP_OVERFLOW_CHECK @@ -253,21 +248,14 @@ memp_init_pool(const struct memp_desc *desc) #endif ); } - -#if MEMP_OVERFLOW_CHECK - memp_overflow_init(desc); -#endif /* MEMP_OVERFLOW_CHECK */ -#endif /* !MEMP_MEM_MALLOC */ - #if MEMP_STATS -#if !MEMP_MEM_MALLOC desc->stats->avail = desc->num; +#endif /* MEMP_STATS */ #endif /* !MEMP_MEM_MALLOC */ -#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY +#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) desc->stats->name = desc->desc; -#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */ -#endif /* MEMP_STATS */ +#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ } /** @@ -483,12 +471,16 @@ memp_free(memp_t type, void *mem) LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + if (mem == NULL) { + return; + } + #if MEMP_OVERFLOW_CHECK >= 2 memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */ #ifdef LWIP_HOOK_MEMP_AVAILABLE - old_first = memp_pools[type].tab; + old_first = *memp_pools[type]->tab; #endif do_memp_free_pool(memp_pools[type], mem); diff --git a/src/core/netif.c b/src/core/netif.c index 86003175..fc9e50b0 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -1,6 +1,20 @@ /** * @file * lwIP network interface abstraction + * + * @defgroup netif Network interface (NETIF) + * @ingroup callbackstyle_api + * + * @defgroup netif_ip4 IPv4 address handling + * @ingroup netif + * + * @defgroup netif_ip6 IPv6 address handling + * @ingroup netif + * + * @defgroup netif_cd Client data handling + * Store data (void*) on a netif for application usage. + * @see @ref LWIP_NUM_NETIF_CLIENT_DATA + * @ingroup netif */ /* @@ -34,31 +48,31 @@ * Author: Adam Dunkels */ -/** - * @defgroup netif Network interface (NETIF) - * @ingroup callbackstyle_api - */ - #include "lwip/opt.h" +#include + #include "lwip/def.h" #include "lwip/ip_addr.h" #include "lwip/ip6_addr.h" #include "lwip/netif.h" #include "lwip/priv/tcp_priv.h" #include "lwip/udp.h" +#include "lwip/raw.h" #include "lwip/snmp.h" #include "lwip/igmp.h" #include "lwip/etharp.h" #include "lwip/stats.h" #include "lwip/sys.h" +#include "lwip/ip.h" #if ENABLE_LOOPBACK -#include "lwip/sys.h" #if LWIP_NETIF_LOOPBACK_MULTITHREADING #include "lwip/tcpip.h" #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ +#include "netif/ethernet.h" + #if LWIP_AUTOIP #include "lwip/autoip.h" #endif /* LWIP_AUTOIP */ @@ -92,6 +106,10 @@ struct netif *netif_default; static u8_t netif_num; +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +static u8_t netif_client_id; +#endif + #define NETIF_REPORT_TYPE_IPV4 0x01 #define NETIF_REPORT_TYPE_IPV6 0x02 static void netif_issue_reports(struct netif* netif, u8_t report_type); @@ -210,8 +228,13 @@ netif_input(struct pbuf *p, struct netif *inp) * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET * to decide whether to forward to ethernet_input() or ip_input(). * In other words, the functions only work when the netif - * driver is implemented correctly! - * + * driver is implemented correctly!\n + * Most members of struct netif should be be initialized by the + * netif init function = netif driver (init parameter of this function).\n + * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after + * setting the MAC address in struct netif.hwaddr + * (IPv6 requires a link-local address). + * * @return netif, or NULL if failed. */ struct netif * @@ -222,7 +245,7 @@ netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input) { #if LWIP_IPV6 - u32_t i; + s8_t i; #endif LWIP_ASSERT("No init function given", init != NULL); @@ -236,20 +259,15 @@ netif_add(struct netif *netif, #if LWIP_IPV6 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { ip_addr_set_zero_ip6(&netif->ip6_addr[i]); - netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); + netif->ip6_addr_state[i] = IP6_ADDR_INVALID; } netif->output_ip6 = netif_null_output_ip6; #endif /* LWIP_IPV6 */ NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); netif->flags = 0; -#if LWIP_DHCP - /* netif not under DHCP control by default */ - netif->dhcp = NULL; -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - /* netif not under AutoIP control by default */ - netif->autoip = NULL; -#endif /* LWIP_AUTOIP */ +#ifdef netif_get_client_data + memset(netif->client_data, 0, sizeof(netif->client_data)); +#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ #if LWIP_IPV6_AUTOCONFIG /* IPv6 address autoconfiguration not enabled by default */ netif->ip6_autoconfig_enabled = 0; @@ -257,10 +275,6 @@ netif_add(struct netif *netif, #if LWIP_IPV6_SEND_ROUTER_SOLICIT netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_IPV6_DHCP6 - /* netif not under DHCPv6 control by default */ - netif->dhcp6 = NULL; -#endif /* LWIP_IPV6_DHCP6 */ #if LWIP_NETIF_STATUS_CALLBACK netif->status_callback = NULL; #endif /* LWIP_NETIF_STATUS_CALLBACK */ @@ -325,7 +339,7 @@ netif_add(struct netif *netif, #if LWIP_IPV4 /** - * @ingroup netif + * @ingroup netif_ip4 * Change IP address configuration for a network interface (including netmask * and default gateway). * @@ -362,6 +376,10 @@ netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t * void netif_remove(struct netif *netif) { +#if LWIP_IPV6 + int i; +#endif + if (netif == NULL) { return; } @@ -369,9 +387,14 @@ netif_remove(struct netif *netif) #if LWIP_IPV4 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { #if LWIP_TCP - tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), NULL); + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); #endif /* LWIP_TCP */ - /* cannot do this for UDP, as there is no 'err' callback in udp pcbs */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_RAW */ } #if LWIP_IGMP @@ -382,10 +405,25 @@ netif_remove(struct netif *netif) #endif /* LWIP_IGMP */ #endif /* LWIP_IPV4*/ -#if LWIP_IPV6 && LWIP_IPV6_MLD +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_RAW */ + } + } +#if LWIP_IPV6_MLD /* stop MLD processing */ mld6_stop(netif); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ if (netif_is_up(netif)) { /* set netif down before removing (call callback function) */ netif_set_down(netif); @@ -456,7 +494,7 @@ netif_find(const char *name) #if LWIP_IPV4 /** - * @ingroup netif + * @ingroup netif_ip4 * Change the IP address of a network interface * * @param netif the network interface to change @@ -468,16 +506,22 @@ netif_find(const char *name) void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) { - ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY); + ip_addr_t new_addr; + *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); + IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); + /* address is actually being changed? */ - if (ip4_addr_cmp(&new_addr, netif_ip4_addr(netif)) == 0) { + if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); #if LWIP_TCP - tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr); + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); #endif /* LWIP_TCP */ #if LWIP_UDP - udp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr); + udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); #endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_RAW */ mib2_remove_ip4(netif); mib2_remove_route_ip4(0, netif); @@ -501,7 +545,7 @@ netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) } /** - * @ingroup netif + * @ingroup netif_ip4 * Change the default gateway for a network interface * * @param netif the network interface to change @@ -523,7 +567,7 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw) } /** - * @ingroup netif + * @ingroup netif_ip4 * Change the netmask of a network interface * * @param netif the network interface to change @@ -694,15 +738,11 @@ netif_set_link_up(struct netif *netif) netif->flags |= NETIF_FLAG_LINK_UP; #if LWIP_DHCP - if (netif->dhcp) { - dhcp_network_changed(netif); - } + dhcp_network_changed(netif); #endif /* LWIP_DHCP */ #if LWIP_AUTOIP - if (netif->autoip) { - autoip_network_changed(netif); - } + autoip_network_changed(netif); #endif /* LWIP_AUTOIP */ if (netif->flags & NETIF_FLAG_UP) { @@ -761,7 +801,7 @@ netif_loop_output(struct netif *netif, struct pbuf *p) err_t err; struct pbuf *last; #if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = 0; + u16_t clen = 0; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ /* If we have a loopif, SNMP counters are adjusted for it, * if not they are adjusted for 'netif'. */ @@ -946,7 +986,153 @@ netif_poll_all(void) #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +/** + * @ingroup netif_cd + * Allocate an index to store data in client_data member of struct netif. + * Returned value is an index in mentioned array. + * @see LWIP_NUM_NETIF_CLIENT_DATA + */ +u8_t +netif_alloc_client_data_id(void) +{ + u8_t result = netif_client_id; + netif_client_id++; + + LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); + return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; +} +#endif + #if LWIP_IPV6 +/** + * @ingroup netif_ip6 + * Change an IPv6 address of a network interface + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param addr6 the new IPv6 address + * + * @note call netif_ip6_addr_set_state() to set the address valid/temptative + */ +void +netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) +{ + LWIP_ASSERT("addr6 != NULL", addr6 != NULL); + netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], + addr6->addr[2], addr6->addr[3]); +} + +/* + * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param i0 word0 of the new IPv6 address + * @param i1 word1 of the new IPv6 address + * @param i2 word2 of the new IPv6 address + * @param i3 word3 of the new IPv6 address + */ +void +netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) +{ + const ip6_addr_t *old_addr; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_addr = netif_ip6_addr(netif, addr_idx); + /* address is actually being changed? */ + if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || + (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { +#if LWIP_TCP || LWIP_UDP + ip_addr_t new_ipaddr; + IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); +#endif /* LWIP_TCP || LWIP_UDP */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_RAW */ + } + /* @todo: remove/readd mib2 ip6 entries? */ + + IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); + IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + NETIF_STATUS_CALLBACK(netif); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + +/** + * @ingroup netif_ip6 + * Change the state of an IPv6 address of a network interface + * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE + * includes the number of checks done, see ip6_addr.h) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param state the new IPv6 address state + */ +void +netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) +{ + u8_t old_state; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_state = netif_ip6_addr_state(netif, addr_idx); + /* state is actually being changed? */ + if (old_state != state) { + u8_t old_valid = old_state & IP6_ADDR_VALID; + u8_t new_valid = state & IP6_ADDR_VALID; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); + + if (old_valid && !new_valid) { + /* address about to be removed by setting invalid */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_RAW */ + /* @todo: remove mib2 ip6 entries? */ + } + netif->ip6_addr_state[addr_idx] = state; + + if (!old_valid && new_valid) { + /* address added by setting valid */ + /* @todo: add mib2 ip6 entries? */ + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + } + if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { + /* address state has changed (valid flag changed or switched between + preferred and deprecated) -> call the callback function */ + NETIF_STATUS_CALLBACK(netif); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + /** * Checks if a specific address is assigned to the netif and returns its * index. @@ -970,7 +1156,7 @@ netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) } /** - * @ingroup netif + * @ingroup netif_ip6 * Create a link-local IPv6 address on a netif (stored in slot 0) * * @param netif the netif to create the address on @@ -989,11 +1175,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) /* Generate interface ID. */ if (from_mac_48bit) { /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | ((u32_t)(netif->hwaddr[1]) << 16) | ((u32_t)(netif->hwaddr[2]) << 8) | (0xff)); - ip_2_ip6(&netif->ip6_addr[0])->addr[3] = htonl((0xfeul << 24) | + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | ((u32_t)(netif->hwaddr[3]) << 16) | ((u32_t)(netif->hwaddr[4]) << 8) | (netif->hwaddr[5])); @@ -1022,7 +1208,7 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) } /** - * @ingroup netif + * @ingroup netif_ip6 * This function allows for the easy addition of a new IPv6 address to an interface. * It takes care of finding an empty slot and then sets the address tentative * (to make sure that all the subsequent processing happens). diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 671397cd..887dc8aa 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -32,6 +32,49 @@ * * Therefore, looping through a pbuf of a single packet, has an * loop end condition (tot_len == p->len), NOT (next == NULL). + * + * Example of custom pbuf usage for zero-copy RX: + @code{.c} +typedef struct my_custom_pbuf +{ + struct pbuf_custom p; + void* dma_descriptor; +} my_custom_pbuf_t; + +LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool"); + +void my_pbuf_free_custom(void* p) +{ + my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p; + + LOCK_INTERRUPTS(); + free_rx_dma_descriptor(my_pbuf->dma_descriptor); + LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf); + UNLOCK_INTERRUPTS(); +} + +void eth_rx_irq() +{ + dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet(); + my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL); + + my_pbuf->p.custom_free_function = my_pbuf_free_custom; + my_pbuf->dma_descriptor = dma_desc; + + invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length); + + struct pbuf* p = pbuf_alloced_custom(PBUF_RAW, + dma_desc->rx_length, + PBUF_REF, + &my_pbuf->p, + dma_desc->rx_data, + dma_desc->max_buffer_size); + + if(netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } +} + @endcode */ /* @@ -743,10 +786,10 @@ pbuf_free(struct pbuf *p) * @param p first pbuf of chain * @return the number of pbufs in a chain */ -u8_t -pbuf_clen(struct pbuf *p) +u16_t +pbuf_clen(const struct pbuf *p) { - u8_t len; + u16_t len; len = 0; while (p != NULL) { @@ -766,12 +809,9 @@ pbuf_clen(struct pbuf *p) void pbuf_ref(struct pbuf *p) { - SYS_ARCH_DECL_PROTECT(old_level); /* pbuf given? */ if (p != NULL) { - SYS_ARCH_PROTECT(old_level); - ++(p->ref); - SYS_ARCH_UNPROTECT(old_level); + SYS_ARCH_INC(p->ref, 1); } } @@ -894,12 +934,12 @@ pbuf_dechain(struct pbuf *p) * enough to hold p_from */ err_t -pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) { u16_t offset_to=0, offset_from=0, len; LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", - (void*)p_to, (void*)p_from)); + (const void*)p_to, (const void*)p_from)); /* is the target big enough to hold the source? */ LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && @@ -961,9 +1001,9 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) * @return the number of bytes copied, or 0 on failure */ u16_t -pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) { - struct pbuf *p; + const struct pbuf *p; u16_t left; u16_t buf_copy_len; u16_t copied_total = 0; @@ -985,8 +1025,9 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) } else { /* copy from this buffer. maybe only partially. */ buf_copy_len = p->len - offset; - if (buf_copy_len > len) - buf_copy_len = len; + if (buf_copy_len > len) { + buf_copy_len = len; + } /* copy the necessary parts of the buffer */ MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); copied_total += buf_copy_len; @@ -1048,6 +1089,24 @@ void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) } #endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ +/* Actual implementation of pbuf_skip() but returning const pointer... */ +static const struct pbuf* +pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + const struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + /** * @ingroup pbuf * Skip a number of bytes at the start of a pbuf @@ -1060,18 +1119,7 @@ void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) struct pbuf* pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) { - u16_t offset_left = in_offset; - struct pbuf* q = in; - - /* get the correct pbuf */ - while ((q != NULL) && (q->len <= offset_left)) { - offset_left -= q->len; - q = q->next; - } - if (out_offset != NULL) { - *out_offset = offset_left; - } - return q; + return (struct pbuf*)(size_t)pbuf_skip_const(in, in_offset, out_offset); } /** @@ -1225,7 +1273,7 @@ pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, } #endif /* LWIP_CHECKSUM_ON_COPY */ -/** +/** * @ingroup pbuf * Get one byte from the specified position in a pbuf * WARNING: returns zero for offset >= p->tot_len @@ -1235,16 +1283,34 @@ pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len */ u8_t -pbuf_get_at(struct pbuf* p, u16_t offset) +pbuf_get_at(const struct pbuf* p, u16_t offset) +{ + int ret = pbuf_try_get_at(p, offset); + if (ret >= 0) { + return (u8_t)ret; + } + return 0; +} + +/** + * @ingroup pbuf + * Get one byte from the specified position in a pbuf + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len + */ +int +pbuf_try_get_at(const struct pbuf* p, u16_t offset) { u16_t q_idx; - struct pbuf* q = pbuf_skip(p, offset, &q_idx); + const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx); /* return requested data if pbuf is OK */ if ((q != NULL) && (q->len > q_idx)) { return ((u8_t*)q->payload)[q_idx]; } - return 0; + return -1; } /** @@ -1280,29 +1346,33 @@ pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) * (0xffff if p is too short, diffoffset+1 otherwise) */ u16_t -pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n) { u16_t start = offset; - struct pbuf* q = p; - - /* get the correct pbuf */ + const struct pbuf* q = p; + u16_t i; + + /* pbuf long enough to perform check? */ + if(p->tot_len < (offset + n)) { + return 0xffff; + } + + /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */ while ((q != NULL) && (q->len <= start)) { start -= q->len; q = q->next; } + /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->len > start)) { - u16_t i; - for (i = 0; i < n; i++) { - u8_t a = pbuf_get_at(q, start + i); - u8_t b = ((const u8_t*)s2)[i]; - if (a != b) { - return i+1; - } + for (i = 0; i < n; i++) { + /* We know pbuf_get_at() succeeds because of p->tot_len check above. */ + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((const u8_t*)s2)[i]; + if (a != b) { + return i+1; } - return 0; } - return 0xffff; + return 0; } /** @@ -1318,7 +1388,7 @@ pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) * @return 0xFFFF if substr was not found in p or the index where it was found */ u16_t -pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) { u16_t i; u16_t max = p->tot_len - mem_len; @@ -1345,7 +1415,7 @@ pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) * @return 0xFFFF if substr was not found in p or the index where it was found */ u16_t -pbuf_strstr(struct pbuf* p, const char* substr) +pbuf_strstr(const struct pbuf* p, const char* substr) { size_t substr_len; if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { diff --git a/src/core/raw.c b/src/core/raw.c index 90f2e302..f692c9c2 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -4,6 +4,13 @@ * different types of protocols besides (or overriding) those * already available in lwIP.\n * See also @ref raw_raw + * + * @defgroup raw_raw RAW + * @ingroup callbackstyle_api + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP.\n + * @see @ref raw_api */ /* @@ -38,21 +45,6 @@ * */ -/** - * @defgroup raw_api RAW API - * @ingroup callbackstyle_api - * @verbinclude "rawapi.txt" - */ - -/** - * @defgroup raw_raw RAW - * @ingroup raw_api - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP.\n - * @see @ref raw_api - */ - #include "lwip/opt.h" #if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ @@ -88,7 +80,7 @@ raw_input_match(struct raw_pcb *pcb, u8_t broadcast) return 1; } #endif /* LWIP_IPV4 && LWIP_IPV6 */ - + /* Only need to check PCB if incoming IP version matches PCB IP version */ if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { #if LWIP_IPV4 @@ -111,7 +103,7 @@ raw_input_match(struct raw_pcb *pcb, u8_t broadcast) return 1; } } - + return 0; } @@ -204,7 +196,7 @@ raw_input(struct pbuf *p, struct netif *inp) * Bind a RAW PCB. * * @param pcb RAW PCB to be bound with a local address ipaddr. - * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to * bind to all local interfaces. * * @return lwIP error code. @@ -258,9 +250,6 @@ raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) * packet will not be passed to other raw PCBs or other protocol layers. * - not free the packet, and return zero. The packet will be matched * against further PCBs and/or forwarded to another protocol layers. - * - * @return non-zero if the packet was free()d, zero if the packet remains - * available for others. */ void raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) @@ -291,7 +280,6 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) const ip_addr_t *src_ip; struct pbuf *q; /* q will be sent down the stack */ s16_t header_size; - const ip_addr_t *dst_ip = ipaddr; if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { return ERR_VAL; @@ -332,10 +320,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) } } - netif = ip_route(&pcb->local_ip, dst_ip); + netif = ip_route(&pcb->local_ip, ipaddr); if (netif == NULL) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); - ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip); + ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { pbuf_free(q); @@ -360,7 +348,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) if (ip_addr_isany(&pcb->local_ip)) { /* use outgoing network interface IP address as source address */ - src_ip = ip_netif_get_local_ip(netif, dst_ip); + src_ip = ip_netif_get_local_ip(netif, ipaddr); #if LWIP_IPV6 if (src_ip == NULL) { if (q != p) { @@ -377,15 +365,15 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) #if LWIP_IPV6 /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, compute the checksum and update the checksum in the payload. */ - if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) { - u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip)); + if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) { + u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr)); LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); } #endif NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); - err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif); + err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); NETIF_SET_HWADDRHINT(netif, NULL); /* did we chain a header earlier? */ @@ -479,7 +467,9 @@ raw_new(u8_t proto) * @return The RAW PCB which was created. NULL if the PCB data structure * could not be allocated. * - * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. * @param proto the protocol number (next header) of the IPv6 packet payload * (e.g. IP6_NEXTH_ICMP6) * @@ -501,4 +491,25 @@ raw_new_ip_type(u8_t type, u8_t proto) return pcb; } +/** This function is called from netif.c when address is changed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change + */ +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct raw_pcb* rpcb; + + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { + for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(rpcb->local_ip, *new_addr); + } + } + } +} + #endif /* LWIP_RAW */ diff --git a/src/core/tcp.c b/src/core/tcp.c index 37348281..1d700980 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -2,6 +2,15 @@ * @file * Transmission Control Protocol for IP * See also @ref tcp_raw + * + * @defgroup tcp_raw TCP + * @ingroup callbackstyle_api + * Transmission Control Protocol for IP\n + * @see @ref raw_api and @ref netconn + * + * Common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n */ /* @@ -36,17 +45,6 @@ * */ -/** - * @defgroup tcp_raw TCP - * @ingroup raw_api - * Transmission Control Protocol for IP\n - * @see @ref raw_api and @ref netconn - * - * Common functions for the TCP implementation, such as functinos - * for manipulating the data structures and the TCP timer functions. TCP functions - * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n - */ - #include "lwip/opt.h" #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ @@ -87,7 +85,7 @@ #define INITIAL_MSS TCP_MSS #endif -const char * const tcp_state_str[] = { +static const char * const tcp_state_str[] = { "CLOSED", "LISTEN", "SYN_SENT", @@ -106,10 +104,10 @@ static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; /* Incremented every coarse grained timer shot (typically every 500 ms). */ u32_t tcp_ticks; -const u8_t tcp_backoff[13] = +static const u8_t tcp_backoff[13] = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; /* Times per slowtmr hits */ -const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; +static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; /* The TCP PCB lists. */ @@ -531,7 +529,7 @@ tcp_abort(struct tcp_pcb *pcb) * * @param pcb the tcp_pcb to bind (no check is done whether this pcb is * already bound!) - * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind * to any local address * @param port the local port to bind to * @return ERR_USE if the port is already in use @@ -548,7 +546,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) #if LWIP_IPV4 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ if (ipaddr == NULL) { - ipaddr = IP_ADDR_ANY; + ipaddr = IP4_ADDR_ANY; } #endif /* LWIP_IPV4 */ @@ -690,7 +688,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) #endif /* LWIP_CALLBACK_API */ #if TCP_LISTEN_BACKLOG lpcb->accepts_pending = 0; - lpcb->backlog = backlog; + tcp_backlog_set(lpcb, backlog); #endif /* TCP_LISTEN_BACKLOG */ TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); return (struct tcp_pcb *)lpcb; @@ -1096,7 +1094,9 @@ tcp_slowtmr_start: /* If the PCB should be removed, do it. */ if (pcb_remove) { struct tcp_pcb *pcb2; - tcp_err_fn err_fn; +#if LWIP_CALLBACK_API + tcp_err_fn err_fn = pcb->errf; +#endif /* LWIP_CALLBACK_API */ void *err_arg; tcp_pcb_purge(pcb); /* Remove PCB from tcp_active_pcbs list. */ @@ -1114,7 +1114,6 @@ tcp_slowtmr_start: pcb->local_port, pcb->remote_port); } - err_fn = pcb->errf; err_arg = pcb->callback_arg; pcb2 = pcb; pcb = pcb->next; @@ -1603,7 +1602,9 @@ tcp_new(void) * place it on any of the TCP PCB lists. * The pcb is not put on any list until binding using tcp_bind(). * - * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) connections, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. * @return a new tcp_pcb that initially is in state CLOSED */ struct tcp_pcb * @@ -1680,6 +1681,8 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) * Used to specify the function that should be called when a fatal error * has occurred on the connection. * + * @note The corresponding pcb is already freed when this callback is called! + * * @param pcb tcp_pcb to set the err callback * @param err callback function to call for this pcb when a fatal error * has occurred on the connection @@ -1897,19 +1900,18 @@ tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest } #endif /* TCP_CALCULATE_EFF_SEND_MSS */ -#if LWIP_IPV4 -/** Helper function for tcp_netif_ipv4_addr_changed() that iterates a pcb list */ +/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */ static void -tcp_netif_ipv4_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list) +tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) { struct tcp_pcb *pcb; pcb = pcb_list; while (pcb != NULL) { /* PCB bound to current local interface address? */ - if (IP_IS_V4_VAL(pcb->local_ip) && ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr) + if (ip_addr_cmp(&pcb->local_ip, old_addr) #if LWIP_AUTOIP /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ - && !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)) + && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) #endif /* LWIP_AUTOIP */ ) { /* this connection must be aborted */ @@ -1925,35 +1927,32 @@ tcp_netif_ipv4_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* /** This function is called from netif.c when address is changed or netif is removed * - * @param old_addr IPv4 address of the netif before change - * @param new_addr IPv4 address of the netif after change or NULL if netif has been removed + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change or NULL if netif has been removed */ void -tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr) +tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) { struct tcp_pcb_listen *lpcb, *next; - tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_active_pcbs); - tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_bound_pcbs); + if (!ip_addr_isany(old_addr)) { + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); - if (!ip4_addr_isany(new_addr)) { - /* PCB bound to current local interface address? */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { - next = lpcb->next; - /* Is this an IPv4 pcb? */ - if (IP_IS_V4_VAL(lpcb->local_ip)) { + if (!ip_addr_isany(new_addr)) { + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; /* PCB bound to current local interface address? */ - if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) && - (ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) { + if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr); + * is set to listen to the new one instead */ + ip_addr_copy(lpcb->local_ip, *new_addr); } } } } } -#endif /* LWIP_IPV4 */ const char* tcp_debug_state_str(enum tcp_state s) @@ -1973,13 +1972,13 @@ tcp_debug_print(struct tcp_hdr *tcphdr) LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - ntohs(tcphdr->src), ntohs(tcphdr->dest))); + lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", - ntohl(tcphdr->seqno))); + lwip_ntohl(tcphdr->seqno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", - ntohl(tcphdr->ackno))); + lwip_ntohl(tcphdr->ackno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", TCPH_HDRLEN(tcphdr), @@ -1989,12 +1988,12 @@ tcp_debug_print(struct tcp_hdr *tcphdr) (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1), (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1), (u16_t)(TCPH_FLAGS(tcphdr) & 1), - ntohs(tcphdr->wnd))); + lwip_ntohs(tcphdr->wnd))); tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", - ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 80e47ba7..93268b34 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -55,7 +55,6 @@ #include "lwip/stats.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" #if LWIP_ND6_TCP_REACHABILITY_HINTS #include "lwip/nd6.h" #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ @@ -199,7 +198,7 @@ tcp_input(struct pbuf *p, struct netif *inp) /* remember the pointer to the second part of the options */ tcphdr_opt2 = (u8_t*)p->next->payload; - + /* advance p->next to point after the options, and manually adjust p->tot_len to keep it consistent with the changed p->next */ pbuf_header(p->next, -(s16_t)opt2len); @@ -210,11 +209,11 @@ tcp_input(struct pbuf *p, struct netif *inp) } /* Convert fields in TCP header to host byte order. */ - tcphdr->src = ntohs(tcphdr->src); - tcphdr->dest = ntohs(tcphdr->dest); - seqno = tcphdr->seqno = ntohl(tcphdr->seqno); - ackno = tcphdr->ackno = ntohl(tcphdr->ackno); - tcphdr->wnd = ntohs(tcphdr->wnd); + tcphdr->src = lwip_ntohs(tcphdr->src); + tcphdr->dest = lwip_ntohs(tcphdr->dest); + seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno); + tcphdr->wnd = lwip_ntohs(tcphdr->wnd); flags = TCPH_FLAGS(tcphdr); tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); @@ -535,10 +534,7 @@ dropped: * connection (from tcp_input()). * * @param pcb the tcp_pcb_listen for which a segment arrived - * @return ERR_OK if the segment was processed - * another err_t on error * - * @note the return value is not (yet?) used in tcp_input() * @note the segment which arrived is saved in global variables, therefore only the pcb * involved is passed as a parameter to this function */ @@ -748,7 +744,7 @@ tcp_process(struct tcp_pcb *pcb) switch (pcb->state) { case SYN_SENT: LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, - pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); /* received SYN ACK with expected sequence number? */ if ((flags & TCP_ACK) && (flags & TCP_SYN) && (ackno == pcb->lastack + 1)) { @@ -887,7 +883,8 @@ tcp_process(struct tcp_pcb *pcb) case FIN_WAIT_1: tcp_receive(pcb); if (recv_flags & TF_GOT_FIN) { - if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_ack_now(pcb); @@ -899,7 +896,8 @@ tcp_process(struct tcp_pcb *pcb) tcp_ack_now(pcb); pcb->state = CLOSING; } - } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { pcb->state = FIN_WAIT_2; } break; @@ -916,7 +914,7 @@ tcp_process(struct tcp_pcb *pcb) break; case CLOSING: tcp_receive(pcb); - if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_pcb_purge(pcb); TCP_RMV_ACTIVE(pcb); @@ -926,7 +924,7 @@ tcp_process(struct tcp_pcb *pcb) break; case LAST_ACK: tcp_receive(pcb); - if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ recv_flags |= TF_CLOSED; @@ -997,7 +995,6 @@ tcp_receive(struct tcp_pcb *pcb) #if TCP_QUEUE_OOSEQ struct tcp_seg *prev, *cseg; #endif /* TCP_QUEUE_OOSEQ */ - struct pbuf *p; s32_t off; s16_t m; u32_t right_wnd_edge; @@ -1140,18 +1137,18 @@ tcp_receive(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", ackno, pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno): 0, + lwip_ntohl(pcb->unacked->tcphdr->seqno): 0, pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); /* Remove segment from the unacknowledged list if the incoming ACK acknowledges them. */ while (pcb->unacked != NULL && - TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked), ackno)) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", - ntohl(pcb->unacked->tcphdr->seqno), - ntohl(pcb->unacked->tcphdr->seqno) + + lwip_ntohl(pcb->unacked->tcphdr->seqno), + lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked))); next = pcb->unacked; @@ -1199,10 +1196,10 @@ tcp_receive(struct tcp_pcb *pcb) ->unsent list after a retransmission, so these segments may in fact have been sent once. */ while (pcb->unsent != NULL && - TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", - ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent))); next = pcb->unsent; @@ -1314,8 +1311,8 @@ tcp_receive(struct tcp_pcb *pcb) adjust the ->data pointer in the seg and the segment length.*/ + struct pbuf *p = inseg.p; off = pcb->rcv_nxt - seqno; - p = inseg.p; LWIP_ASSERT("inseg.p != NULL", inseg.p); LWIP_ASSERT("insane offset!", (off < 0x7fff)); if (inseg.p->len < off) { @@ -1779,12 +1776,12 @@ tcp_parseopt(struct tcp_pcb *pcb) tsval |= (tcp_getoptbyte() << 16); tsval |= (tcp_getoptbyte() << 24); if (flags & TCP_SYN) { - pcb->ts_recent = ntohl(tsval); + pcb->ts_recent = lwip_ntohl(tsval); /* Enable sending timestamps in every segment now that we know the remote host supports it. */ pcb->flags |= TF_TIMESTAMP; } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { - pcb->ts_recent = ntohl(tsval); + pcb->ts_recent = lwip_ntohl(tsval); } /* Advance to next option (6 bytes already read) */ tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 30289791..3c2bc81a 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -52,7 +52,6 @@ #include "lwip/stats.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" #if LWIP_TCP_TIMESTAMPS #include "lwip/sys.h" #endif @@ -115,12 +114,12 @@ tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= TCP_HLEN + optlen)); tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = htons(pcb->local_port); - tcphdr->dest = htons(pcb->remote_port); + tcphdr->src = lwip_htons(pcb->local_port); + tcphdr->dest = lwip_htons(pcb->remote_port); tcphdr->seqno = seqno_be; - tcphdr->ackno = htonl(pcb->rcv_nxt); + tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); - tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); tcphdr->chksum = 0; tcphdr->urgp = 0; @@ -205,9 +204,9 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, return NULL; } seg->tcphdr = (struct tcp_hdr *)seg->p->payload; - seg->tcphdr->src = htons(pcb->local_port); - seg->tcphdr->dest = htons(pcb->remote_port); - seg->tcphdr->seqno = htonl(seqno); + seg->tcphdr->src = lwip_htons(pcb->local_port); + seg->tcphdr->dest = lwip_htons(pcb->remote_port); + seg->tcphdr->seqno = lwip_htonl(seqno); /* ackno is set in tcp_output */ TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); /* wnd and chksum are set in tcp_output */ @@ -225,7 +224,7 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, * @param length size of the pbuf's payload. * @param max_length maximum usable size of payload+oversize. * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. - * @param pcb The TCP connection that willo enqueue the pbuf. + * @param pcb The TCP connection that will enqueue the pbuf. * @param apiflags API flags given to tcp_write. * @param first_seg true when this pbuf will be used in the first enqueued segment. */ @@ -243,7 +242,6 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, LWIP_UNUSED_ARG(pcb); LWIP_UNUSED_ARG(apiflags); LWIP_UNUSED_ARG(first_seg); - /* always create MSS-sized pbufs */ alloc = max_length; #else /* LWIP_NETIF_TX_SINGLE_PBUF */ if (length < max_length) { @@ -350,6 +348,7 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len) } /** + * @ingroup tcp_raw * Write data for sending (but does not send it immediately). * * It waits in the expectation of more data being sent soon (as @@ -633,8 +632,8 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) prev_seg = seg; LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", - ntohl(seg->tcphdr->seqno), - ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); pos += seglen; } @@ -808,8 +807,8 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", - ntohl(seg->tcphdr->seqno), - ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), (u16_t)flags)); /* Now append seg to pcb->unsent queue */ @@ -856,8 +855,8 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) { /* Pad with two NOP options to make everything nicely aligned */ opts[0] = PP_HTONL(0x0101080A); - opts[1] = htonl(sys_now()); - opts[2] = htonl(pcb->ts_recent); + opts[1] = lwip_htonl(sys_now()); + opts[2] = lwip_htonl(pcb->ts_recent); } #endif @@ -874,7 +873,8 @@ tcp_build_wnd_scale_option(u32_t *opts) } #endif -/** Send an ACK without data. +/** + * Send an ACK without data. * * @param pcb Protocol control block for the TCP connection to send the ACK */ @@ -895,7 +895,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb) } #endif - p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); if (p == NULL) { /* let tcp_fasttmr retry sending this ACK */ pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); @@ -946,6 +946,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb) } /** + * @ingroup tcp_raw * Find out what we can send and send it * * @param pcb Protocol control block for the TCP connection to send data @@ -987,7 +988,7 @@ tcp_output(struct tcp_pcb *pcb) */ if (pcb->flags & TF_ACK_NOW && (seg == NULL || - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { return tcp_send_empty_ack(pcb); } @@ -1028,13 +1029,13 @@ tcp_output(struct tcp_pcb *pcb) ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", pcb->snd_wnd, pcb->cwnd, wnd, - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, - ntohl(seg->tcphdr->seqno), pcb->lastack)); + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); } #endif /* TCP_CWND_DEBUG */ /* data available and window allows it to be sent? */ while (seg != NULL && - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { LWIP_ASSERT("RST not expected here!", (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); /* Stop sending if the nagle algorithm would prevent it @@ -1051,9 +1052,9 @@ tcp_output(struct tcp_pcb *pcb) #if TCP_CWND_DEBUG LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", pcb->snd_wnd, pcb->cwnd, wnd, - ntohl(seg->tcphdr->seqno) + seg->len - + lwip_ntohl(seg->tcphdr->seqno) + seg->len - pcb->lastack, - ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); ++i; #endif /* TCP_CWND_DEBUG */ @@ -1074,7 +1075,7 @@ tcp_output(struct tcp_pcb *pcb) if (pcb->state != SYN_SENT) { pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); } - snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { pcb->snd_nxt = snd_nxt; } @@ -1090,11 +1091,11 @@ tcp_output(struct tcp_pcb *pcb) /* In the case of fast retransmit, the packet should not go to the tail * of the unacked queue, but rather somewhere before it. We need to check for * this case. -STJ Jul 27, 2004 */ - if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { /* add segment to before tail of unacked list, keeping the list sorted */ struct tcp_seg **cur_seg = &(pcb->unacked); while (*cur_seg && - TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { cur_seg = &((*cur_seg)->next ); } seg->next = (*cur_seg); @@ -1145,18 +1146,18 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif /* The TCP header has already been constructed, but the ackno and wnd fields remain. */ - seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); /* advertise our receive window size in this TCP segment */ #if LWIP_WND_SCALE if (seg->flags & TF_SEG_OPTS_WND_SCALE) { /* The Window field in a SYN segment itself (the only type where we send the window scale option) is never scaled. */ - seg->tcphdr->wnd = htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); } else #endif /* LWIP_WND_SCALE */ { - seg->tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); } pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; @@ -1198,12 +1199,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif if (pcb->rttest == 0) { pcb->rttest = tcp_ticks; - pcb->rtseq = ntohl(seg->tcphdr->seqno); + pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); } LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", - htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + seg->len)); len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); @@ -1301,10 +1302,10 @@ tcp_rst(u32_t seqno, u32_t ackno, (p->len >= sizeof(struct tcp_hdr))); tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = htons(local_port); - tcphdr->dest = htons(remote_port); - tcphdr->seqno = htonl(seqno); - tcphdr->ackno = htonl(ackno); + tcphdr->src = lwip_htons(local_port); + tcphdr->dest = lwip_htons(remote_port); + tcphdr->seqno = lwip_htonl(seqno); + tcphdr->ackno = lwip_htonl(ackno); TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); #if LWIP_WND_SCALE tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); @@ -1376,7 +1377,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) /** * Requeue the first unacked segment for retransmission * - * Called by tcp_receive() for fast retramsmit. + * Called by tcp_receive() for fast retransmit. * * @param pcb the tcp_pcb for which to retransmit the first unacked segment */ @@ -1397,7 +1398,7 @@ tcp_rexmit(struct tcp_pcb *pcb) cur_seg = &(pcb->unsent); while (*cur_seg && - TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { cur_seg = &((*cur_seg)->next ); } seg->next = *cur_seg; @@ -1435,7 +1436,7 @@ tcp_rexmit_fast(struct tcp_pcb *pcb) ("tcp_receive: dupacks %"U16_F" (%"U32_F "), fast retransmit %"U32_F"\n", (u16_t)pcb->dupacks, pcb->lastack, - ntohl(pcb->unacked->tcphdr->seqno))); + lwip_ntohl(pcb->unacked->tcphdr->seqno))); tcp_rexmit(pcb); /* Set ssthresh to half of the minimum of the current @@ -1486,7 +1487,7 @@ tcp_keepalive(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); - p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); if (p == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n")); @@ -1535,6 +1536,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) struct tcp_seg *seg; u16_t len; u8_t is_fin; + u32_t snd_nxt; struct netif *netif; LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); @@ -1579,6 +1581,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); } + /* The byte may be acknowledged without the window being opened. */ + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); if (netif == NULL) { err = ERR_RTE; diff --git a/src/core/timeouts.c b/src/core/timeouts.c index fcba0a1a..e2dc0fc7 100644 --- a/src/core/timeouts.c +++ b/src/core/timeouts.c @@ -360,7 +360,6 @@ sys_check_timeouts(void) } } -#if NO_SYS /** Set back the timestamp of the last call to sys_check_timeouts() * This is necessary if sys_check_timeouts() hasn't been called for a long * time (e.g. while saving energy) to prevent all timer functions of that @@ -371,7 +370,6 @@ sys_restart_timeouts(void) { timeouts_last_time = sys_now(); } -#endif /* NO_SYS */ /** Return the time left before the next timeout is due. If no timeouts are * enqueued, returns 0xffffffff diff --git a/src/core/udp.c b/src/core/udp.c index 14130ab3..f9aee732 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -1,7 +1,13 @@ /** * @file * User Datagram Protocol module\n + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n * See also @ref udp_raw + * + * @defgroup udp_raw UDP + * @ingroup callbackstyle_api + * User Datagram Protocol module\n + * @see @ref raw_api and @ref netconn */ /* @@ -36,19 +42,6 @@ * */ -/** - * @defgroup udp_raw UDP - * @ingroup raw_api - * User Datagram Protocol module\n - * @see @ref raw_api and @ref netconn - */ - -/* udp.c - * - * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). - * - */ - /* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! */ @@ -63,7 +56,6 @@ #include "lwip/ip_addr.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" #include "lwip/netif.h" #include "lwip/icmp.h" #include "lwip/icmp6.h" @@ -198,7 +190,7 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) return 1; } } - + return 0; } @@ -250,17 +242,17 @@ udp_input(struct pbuf *p, struct netif *inp) LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); /* convert src and dest ports to host byte order */ - src = ntohs(udphdr->src); - dest = ntohs(udphdr->dest); + src = lwip_ntohs(udphdr->src); + dest = lwip_ntohs(udphdr->dest); udp_debug_print(udphdr); /* print the UDP source and destination */ LWIP_DEBUGF(UDP_DEBUG, ("udp (")); ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest))); ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src))); pcb = NULL; prev = NULL; @@ -339,7 +331,7 @@ udp_input(struct pbuf *p, struct netif *inp) #if LWIP_UDPLITE if (ip_current_header_proto() == IP_PROTO_UDPLITE) { /* Do the UDP Lite checksum */ - u16_t chklen = ntohs(udphdr->len); + u16_t chklen = lwip_ntohs(udphdr->len); if (chklen < sizeof(struct udp_hdr)) { if (chklen == 0) { /* For UDP-Lite, checksum length of 0 means checksum @@ -760,8 +752,8 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d (q->len >= sizeof(struct udp_hdr))); /* q now represents the packet to be sent */ udphdr = (struct udp_hdr *)q->payload; - udphdr->src = htons(pcb->local_port); - udphdr->dest = htons(dst_port); + udphdr->src = lwip_htons(pcb->local_port); + udphdr->dest = lwip_htons(dst_port); /* in UDP, 0 checksum means 'no checksum' */ udphdr->chksum = 0x0000; @@ -794,7 +786,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d chklen_hdr = 0; chklen = q->tot_len; } - udphdr->len = htons(chklen_hdr); + udphdr->len = lwip_htons(chklen_hdr); /* calculate checksum */ #if CHECKSUM_GEN_UDP IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { @@ -825,7 +817,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d #endif /* LWIP_UDPLITE */ { /* UDP */ LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); - udphdr->len = htons(q->tot_len); + udphdr->len = lwip_htons(q->tot_len); /* calculate checksum */ #if CHECKSUM_GEN_UDP IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { @@ -859,7 +851,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d /* Determine TTL to use */ #if LWIP_MULTICAST_TX_OPTIONS - ttl = (ip_addr_ismulticast(dst_ip) ? pcb->mcast_ttl : pcb->ttl); + ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl); #else /* LWIP_MULTICAST_TX_OPTIONS */ ttl = pcb->ttl; #endif /* LWIP_MULTICAST_TX_OPTIONS */ @@ -891,7 +883,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d * Bind an UDP PCB. * * @param pcb UDP PCB to be bound with a local address ipaddr and port. - * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to * bind to all local interfaces. * @param port local UDP port to bind with. Use 0 to automatically bind * to a random port between UDP_LOCAL_PORT_RANGE_START and @@ -915,7 +907,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) #if LWIP_IPV4 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ if (ipaddr == NULL) { - ipaddr = IP_ADDR_ANY; + ipaddr = IP4_ADDR_ANY; } #endif /* LWIP_IPV4 */ @@ -1141,7 +1133,7 @@ udp_new(void) memset(pcb, 0, sizeof(struct udp_pcb)); pcb->ttl = UDP_TTL; #if LWIP_MULTICAST_TX_OPTIONS - pcb->mcast_ttl = UDP_TTL; + udp_set_multicast_ttl(pcb, UDP_TTL); #endif /* LWIP_MULTICAST_TX_OPTIONS */ } return pcb; @@ -1151,7 +1143,9 @@ udp_new(void) * @ingroup udp_raw * Create a UDP PCB for specific IP type. * - * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. * @return The UDP PCB which was created. NULL if the PCB data structure * could not be allocated. * @@ -1173,32 +1167,26 @@ udp_new_ip_type(u8_t type) return pcb; } -#if LWIP_IPV4 /** This function is called from netif.c when address is changed * - * @param old_addr IPv4 address of the netif before change - * @param new_addr IPv4 address of the netif after change + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change */ -void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr) +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) { struct udp_pcb* upcb; - if (!ip4_addr_isany(new_addr)) { + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { - /* Is this an IPv4 pcb? */ - if (IP_IS_V4_VAL(upcb->local_ip)) { - /* PCB bound to current local interface address? */ - if (!ip4_addr_isany(ip_2_ip4(&upcb->local_ip)) && - ip4_addr_cmp(ip_2_ip4(&upcb->local_ip), old_addr)) { - /* The PCB is bound to the old ipaddr and - * is set to bound to the new one instead */ - ip_addr_copy_from_ip4(upcb->local_ip, *new_addr); - } + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&upcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(upcb->local_ip, *new_addr); } } } } -#endif /* LWIP_IPV4 */ #if UDP_DEBUG /** @@ -1212,10 +1200,10 @@ udp_debug_print(struct udp_hdr *udphdr) LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - ntohs(udphdr->src), ntohs(udphdr->dest))); + lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest))); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", - ntohs(udphdr->len), ntohs(udphdr->chksum))); + lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum))); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); } #endif /* UDP_DEBUG */ diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 8bd8bf1e..e8620dd8 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -139,7 +139,32 @@ enum netconn_state { NETCONN_CLOSE }; -/** Use to inform the callback function about changes */ +/** Used to inform the callback function about changes + * + * Event explanation: + * + * In the netconn implementation, there are three ways to block a client: + * + * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) + * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) + * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) + * + * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking + * connections, you need to know in advance whether a call to a netconn function call would block or not, + * and these events tell you about that. + * + * RCVPLUS events say: Safe to perform a potentially blocking call call once more. + * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe + * to call netconn_accept 3 times without being blocked. + * Same thing for receive mbox. + * + * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". + * Socket implementation decrements the counter. + * + * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. + * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. + * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. + */ enum netconn_evt { NETCONN_EVT_RCVPLUS, NETCONN_EVT_RCVMINUS, @@ -327,7 +352,7 @@ err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); #if LWIP_IPV6 /** @ingroup netconn_common - * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) + * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) */ #define netconn_set_ipv6only(conn, val) do { if(val) { \ (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ diff --git a/src/include/lwip/apps/httpd_opts.h b/src/include/lwip/apps/httpd_opts.h index 5fa84024..340db15f 100644 --- a/src/include/lwip/apps/httpd_opts.h +++ b/src/include/lwip/apps/httpd_opts.h @@ -161,28 +161,6 @@ #define HTTPD_DEBUG_TIMING LWIP_DBG_OFF #endif -/** Set this to 1 on platforms where strnstr is not available */ -#if !defined LWIP_HTTPD_STRNSTR_PRIVATE || defined __DOXYGEN__ -#define LWIP_HTTPD_STRNSTR_PRIVATE 1 -#endif - -/** Set this to 1 on platforms where stricmp is not available */ -#if !defined LWIP_HTTPD_STRICMP_PRIVATE || defined __DOXYGEN__ -#define LWIP_HTTPD_STRICMP_PRIVATE 0 -#endif - -/** Define this to a smaller function if you have itoa() at hand... */ -#if !defined LWIP_HTTPD_ITOA || defined __DOXYGEN__ -#if !defined LWIP_HTTPD_ITOA_PRIVATE || defined __DOXYGEN__ -#define LWIP_HTTPD_ITOA_PRIVATE 1 -#endif -#if LWIP_HTTPD_ITOA_PRIVATE -#define LWIP_HTTPD_ITOA(buffer, bufsize, number) httpd_itoa(number, buffer) -#else -#define LWIP_HTTPD_ITOA(buffer, bufsize, number) snprintf(buffer, bufsize, "%d", number) -#endif -#endif - /** Set this to one to show error pages when parsing a request fails instead of simply closing the connection. */ #if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ diff --git a/src/include/lwip/apps/mdns.h b/src/include/lwip/apps/mdns.h new file mode 100644 index 00000000..f57b182f --- /dev/null +++ b/src/include/lwip/apps/mdns.h @@ -0,0 +1,69 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_H +#define LWIP_HDR_MDNS_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/netif.h" + +#if LWIP_MDNS_RESPONDER + +enum mdns_sd_proto { + DNSSD_PROTO_UDP = 0, + DNSSD_PROTO_TCP = 1 +}; + +#define MDNS_LABEL_MAXLEN 63 + +struct mdns_host; +struct mdns_service; + +/** Callback function to add text to a reply, called when generating the reply */ +typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); + +void mdns_resp_init(void); + +err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); +err_t mdns_resp_remove_netif(struct netif *netif); + +err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); +err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); +void mdns_resp_netif_settings_changed(struct netif *netif); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_H */ diff --git a/src/include/lwip/apps/mdns_opts.h b/src/include/lwip/apps/mdns_opts.h new file mode 100644 index 00000000..a298c5aa --- /dev/null +++ b/src/include/lwip/apps/mdns_opts.h @@ -0,0 +1,74 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#ifndef LWIP_HDR_APPS_MDNS_OPTS_H +#define LWIP_HDR_APPS_MDNS_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup mdns_opts Options + * @ingroup mdns + * @{ + */ + +/** + * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS + * transport. IGMP is needed for IPv4 multicast. + */ +#ifndef LWIP_MDNS_RESPONDER +#define LWIP_MDNS_RESPONDER 0 +#endif /* LWIP_MDNS_RESPONDER */ + +/** The maximum number of services per netif */ +#ifndef MDNS_MAX_SERVICES +#define MDNS_MAX_SERVICES 1 +#endif + +/** + * MDNS_DEBUG: Enable debugging for multicast DNS. + */ +#ifndef MDNS_DEBUG +#define MDNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ + diff --git a/src/include/lwip/apps/mdns_priv.h b/src/include/lwip/apps/mdns_priv.h new file mode 100644 index 00000000..9ae2cef9 --- /dev/null +++ b/src/include/lwip/apps/mdns_priv.h @@ -0,0 +1,66 @@ +/** + * @file + * MDNS responder private definitions + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_PRIV_H +#define LWIP_HDR_MDNS_PRIV_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/pbuf.h" + +#if LWIP_MDNS_RESPONDER + +/* Domain struct and methods - visible for unit tests */ + +#define MDNS_DOMAIN_MAXLEN 256 +#define MDNS_READNAME_ERROR 0xFFFF + +struct mdns_domain { + /* Encoded domain name */ + u8_t name[MDNS_DOMAIN_MAXLEN]; + /* Total length of domain name, including zero */ + u16_t length; + /* Set if compression of this domain is not allowed */ + u8_t skip_compression; +}; + +err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); +u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); +int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); +u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_PRIV_H */ diff --git a/src/include/lwip/apps/netbiosns_opts.h b/src/include/lwip/apps/netbiosns_opts.h index 870b9fdf..0909ef7b 100644 --- a/src/include/lwip/apps/netbiosns_opts.h +++ b/src/include/lwip/apps/netbiosns_opts.h @@ -40,16 +40,6 @@ * @{ */ -/** Since there's no standard function for case-insensitive string comparision, - * we need another define here: - * define this to stricmp() for windows or strcasecmp() for linux. - * If not defined, comparision is case sensitive and the provided hostname must be - * uppercase. - */ -#if !defined NETBIOS_STRCMP || defined __DOXYGEN__ -#define NETBIOS_STRCMP(str1, str2) strcmp(str1, str2) -#endif - /** NetBIOS name of lwip device * This must be uppercase until NETBIOS_STRCMP() is defined to a string * comparision function that is case insensitive. diff --git a/src/include/lwip/apps/snmp.h b/src/include/lwip/apps/snmp.h index 60ce9c92..10e8ff43 100644 --- a/src/include/lwip/apps/snmp.h +++ b/src/include/lwip/apps/snmp.h @@ -99,6 +99,7 @@ void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); err_t snmp_send_trap_generic(s32_t generic_trap); err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); +err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); #define SNMP_AUTH_TRAPS_DISABLED 0 #define SNMP_AUTH_TRAPS_ENABLED 1 diff --git a/src/include/lwip/apps/snmp_core.h b/src/include/lwip/apps/snmp_core.h index 938be509..e781c532 100644 --- a/src/include/lwip/apps/snmp_core.h +++ b/src/include/lwip/apps/snmp_core.h @@ -200,7 +200,7 @@ struct snmp_node_instance u8_t asn1_type; /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ snmp_access_t access; - + /** returns object value for the given object identifier. Return values <0 to indicate an error */ node_instance_get_value_method get_value; /** tests length and/or range BEFORE setting */ @@ -278,7 +278,7 @@ struct snmp_next_oid_state u32_t* next_oid; u8_t next_oid_len; u8_t next_oid_max_len; - + snmp_next_oid_status_t status; void* reference; }; diff --git a/src/include/lwip/apps/snmp_opts.h b/src/include/lwip/apps/snmp_opts.h index bf6f0093..6c9ba7be 100644 --- a/src/include/lwip/apps/snmp_opts.h +++ b/src/include/lwip/apps/snmp_opts.h @@ -283,7 +283,11 @@ #endif #ifndef LWIP_SNMP_V3_CRYPTO -#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 +#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 +#endif + +#ifndef LWIP_SNMP_V3_MBEDTLS +#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3 #endif #endif /* LWIP_HDR_SNMP_OPTS_H */ diff --git a/src/include/lwip/apps/snmp_table.h b/src/include/lwip/apps/snmp_table.h index c08f1aa5..4988b51c 100644 --- a/src/include/lwip/apps/snmp_table.h +++ b/src/include/lwip/apps/snmp_table.h @@ -85,7 +85,7 @@ snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len #define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ - + /** simple read-only table */ typedef enum { SNMP_VARIANT_VALUE_TYPE_U32, diff --git a/src/include/lwip/apps/tftp_opts.h b/src/include/lwip/apps/tftp_opts.h new file mode 100644 index 00000000..6968a803 --- /dev/null +++ b/src/include/lwip/apps/tftp_opts.h @@ -0,0 +1,105 @@ +/****************************************************************//** + * + * @file tftp_opts.h + * + * @author Logan Gunthorpe + * + * @brief Trivial File Transfer Protocol (RFC 1350) implementation options + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_OPTS_H +#define LWIP_HDR_APPS_TFTP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup tftp_opts Options + * @ingroup tftp + * @{ + */ + +/** + * Enable TFTP debug messages + */ +#if !defined TFTP_DEBUG || defined __DOXYGEN__ +#define TFTP_DEBUG LWIP_DBG_ON +#endif + +/** + * TFTP server port + */ +#if !defined TFTP_PORT || defined __DOXYGEN__ +#define TFTP_PORT 69 +#endif + +/** + * TFTP timeout + */ +#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ +#define TFTP_TIMEOUT_MSECS 10000 +#endif + +/** + * Max. number of retries when a file is read from server + */ +#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ +#define TFTP_MAX_RETRIES 5 +#endif + +/** + * TFTP timer cyclic interval + */ +#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ +#define TFTP_TIMER_MSECS 50 +#endif + +/** + * Max. length of TFTP filename + */ +#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ +#define TFTP_MAX_FILENAME_LEN 20 +#endif + +/** + * Max. length of TFTP mode + */ +#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ +#define TFTP_MAX_MODE_LEN 7 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ diff --git a/src/include/lwip/apps/tftp_server.h b/src/include/lwip/apps/tftp_server.h new file mode 100644 index 00000000..3fbe701e --- /dev/null +++ b/src/include/lwip/apps/tftp_server.h @@ -0,0 +1,94 @@ +/****************************************************************//** + * + * @file tftp_server.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_SERVER_H +#define LWIP_HDR_APPS_TFTP_SERVER_H + +#include "lwip/apps/tftp_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup tftp + * TFTP context containing callback functions for TFTP transfers + */ +struct tftp_context { + /** + * Open file for read/write. + * @param fname Filename + * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) + * @param write Flag indicating read (0) or write (!= 0) access + * @returns File handle supplied to other functions + */ + void* (*open)(const char* fname, const char* mode, u8_t write); + /** + * Close file handle + * @param handle File handle returned by open() + */ + void (*close)(void* handle); + /** + * Read from file + * @param handle File handle returned by open() + * @param buf Target buffer to copy read data to + * @param bytes Number of bytes to copy to buf + * @returns >= 0: Success; < 0: Error + */ + int (*read)(void* handle, void* buf, int bytes); + /** + * Write to file + * @param handle File handle returned by open() + * @param pbuf PBUF adjusted such that payload pointer points + * to the beginning of write data. In other words, + * TFTP headers are stripped off. + * @returns >= 0: Success; < 0: Error + */ + int (*write)(void* handle, struct pbuf* p); +}; + +err_t tftp_init(const struct tftp_context* ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/src/include/lwip/arch.h b/src/include/lwip/arch.h index 372cea13..473e4a4a 100644 --- a/src/include/lwip/arch.h +++ b/src/include/lwip/arch.h @@ -48,7 +48,7 @@ #include "arch/cc.h" /** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the stdint.h header. This cannot be \#defined in lwipopts.h since + * the stdint.h header. This cannot be \#defined in lwipopts.h since * this is not an option of lwIP itself, but an option of the lwIP port * to your system. * Additionally, this header is meant to be \#included in lwipopts.h @@ -71,7 +71,7 @@ typedef uintptr_t mem_ptr_t; #endif /** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the inttypes.h header. This cannot be \#defined in lwipopts.h since + * the inttypes.h header. This cannot be \#defined in lwipopts.h since * this is not an option of lwIP itself, but an option of the lwIP port * to your system. * Additionally, this header is meant to be \#included in lwipopts.h @@ -85,7 +85,7 @@ typedef uintptr_t mem_ptr_t; #if !LWIP_NO_INTTYPES_H #include #ifndef X8_F -#define X8_F "02"PRIx8 +#define X8_F "02" PRIx8 #endif #ifndef U16_F #define U16_F PRIu16 @@ -185,142 +185,6 @@ extern "C" { #endif /* LWIP_UNUSED_ARG */ -#ifdef LWIP_PROVIDE_ERRNO - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -#ifndef errno -extern int errno; -#endif - -#endif /* LWIP_PROVIDE_ERRNO */ - #ifdef __cplusplus } #endif diff --git a/src/include/lwip/autoip.h b/src/include/lwip/autoip.h index 81d89932..2f666989 100644 --- a/src/include/lwip/autoip.h +++ b/src/include/lwip/autoip.h @@ -36,9 +36,6 @@ * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform * with RFC 3927. * - * - * Please coordinate changes and requests with Dominik Spies - * */ #ifndef LWIP_HDR_AUTOIP_H @@ -78,7 +75,6 @@ struct autoip }; -#define autoip_init() /* Compatibility define, no init needed. */ void autoip_set_struct(struct netif *netif, struct autoip *autoip); /** Remove a struct autoip previously set to the netif using autoip_set_struct() */ #define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) @@ -89,6 +85,9 @@ void autoip_tmr(void); void autoip_network_changed(struct netif *netif); u8_t autoip_supplied_address(const struct netif *netif); +/* for lwIP internal use by ip4.c */ +u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); + #ifdef __cplusplus } #endif diff --git a/src/include/lwip/debug.h b/src/include/lwip/debug.h index cd6eacff..c6766120 100644 --- a/src/include/lwip/debug.h +++ b/src/include/lwip/debug.h @@ -72,8 +72,8 @@ * -- To disable assertions define LWIP_NOASSERT in arch/cc.h. */ #ifndef LWIP_NOASSERT -#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ - LWIP_PLATFORM_ASSERT(message); } while(0) +#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \ + LWIP_PLATFORM_ASSERT(message); }} while(0) #ifndef LWIP_PLATFORM_ASSERT #error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" #endif diff --git a/src/include/lwip/def.h b/src/include/lwip/def.h index 39d720c0..bb07009c 100644 --- a/src/include/lwip/def.h +++ b/src/include/lwip/def.h @@ -72,32 +72,6 @@ extern "C" { #define LWIP_MAKE_U16(a, b) ((b << 8) | a) #endif -#ifndef LWIP_PLATFORM_BYTESWAP -#define LWIP_PLATFORM_BYTESWAP 0 -#endif - -#ifndef LWIP_PREFIX_BYTEORDER_FUNCS -/* workaround for naming collisions on some platforms */ - -#ifdef htons -#undef htons -#endif /* htons */ -#ifdef htonl -#undef htonl -#endif /* htonl */ -#ifdef ntohs -#undef ntohs -#endif /* ntohs */ -#ifdef ntohl -#undef ntohl -#endif /* ntohl */ - -#define htons(x) lwip_htons(x) -#define ntohs(x) lwip_ntohs(x) -#define htonl(x) lwip_htonl(x) -#define ntohl(x) lwip_ntohl(x) -#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ - #if BYTE_ORDER == BIG_ENDIAN #define lwip_htons(x) (x) #define lwip_ntohs(x) (x) @@ -108,17 +82,23 @@ extern "C" { #define PP_HTONL(x) (x) #define PP_NTOHL(x) (x) #else /* BYTE_ORDER != BIG_ENDIAN */ -#if LWIP_PLATFORM_BYTESWAP -#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) -#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) -#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) -#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) -#else /* LWIP_PLATFORM_BYTESWAP */ +#ifndef lwip_htons u16_t lwip_htons(u16_t x); -u16_t lwip_ntohs(u16_t x); +#endif +#define lwip_ntohs(x) lwip_htons(x) + +#ifndef lwip_htonl u32_t lwip_htonl(u32_t x); -u32_t lwip_ntohl(u32_t x); -#endif /* LWIP_PLATFORM_BYTESWAP */ +#endif +#define lwip_ntohl(x) lwip_htonl(x) + +/* Provide usual function names as macros for users, but this can be turned off */ +#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* These macros should be calculated by the preprocessor and are used with compile-time constants only (so that there is no little-endian @@ -133,9 +113,31 @@ u32_t lwip_ntohl(u32_t x); #endif /* BYTE_ORDER == BIG_ENDIAN */ +/* Functions that are not available as standard implementations. + * In cc.h, you can #define these to implementations available on + * your platform to save some code bytes if you use these functions + * in your application, too. + */ + +#ifndef lwip_itoa +/* This can be #defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform */ +void lwip_itoa(char* result, size_t bufsize, int number); +#endif +#ifndef lwip_strnicmp +/* This can be #defined to strnicmp() or strncasecmp() depending on your platform */ +int lwip_strnicmp(const char* str1, const char* str2, size_t len); +#endif +#ifndef lwip_stricmp +/* This can be #defined to stricmp() or strcasecmp() depending on your platform */ +int lwip_stricmp(const char* str1, const char* str2); +#endif +#ifndef lwip_strnstr +/* This can be #defined to strnstr() depending on your platform */ +char* lwip_strnstr(const char* buffer, const char* token, size_t n); +#endif + #ifdef __cplusplus } #endif #endif /* LWIP_HDR_DEF_H */ - diff --git a/src/include/lwip/dhcp.h b/src/include/lwip/dhcp.h index ca19a2a2..f7503280 100644 --- a/src/include/lwip/dhcp.h +++ b/src/include/lwip/dhcp.h @@ -50,15 +50,19 @@ extern "C" { #endif /** period (in seconds) of the application calling dhcp_coarse_tmr() */ -#define DHCP_COARSE_TIMER_SECS 60 +#define DHCP_COARSE_TIMER_SECS 60 /** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ #define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) /** period (in milliseconds) of the application calling dhcp_fine_tmr() */ -#define DHCP_FINE_TIMER_MSECS 500 +#define DHCP_FINE_TIMER_MSECS 500 -#define DHCP_CHADDR_LEN 16U -#define DHCP_SNAME_LEN 64U -#define DHCP_FILE_LEN 128U +#define DHCP_BOOT_FILE_LEN 128U + +/* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ +typedef enum { + DHCP_AUTOIP_COOP_STATE_OFF = 0, + DHCP_AUTOIP_COOP_STATE_ON = 1 +} dhcp_autoip_coop_state_enum_t; struct dhcp { @@ -96,183 +100,31 @@ struct dhcp u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ #if LWIP_DHCP_BOOTP_FILE - ip_addr_t offered_si_addr; - char boot_file_name[DHCP_FILE_LEN]; + ip4_addr_t offered_si_addr; + char boot_file_name[DHCP_BOOT_FILE_LEN]; #endif /* LWIP_DHCP_BOOTPFILE */ }; -/* MUST be compiled with "pack structs" or equivalent! */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** minimum set of fields of any DHCP message */ -struct dhcp_msg -{ - PACK_STRUCT_FLD_8(u8_t op); - PACK_STRUCT_FLD_8(u8_t htype); - PACK_STRUCT_FLD_8(u8_t hlen); - PACK_STRUCT_FLD_8(u8_t hops); - PACK_STRUCT_FIELD(u32_t xid); - PACK_STRUCT_FIELD(u16_t secs); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); - PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); - PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); - PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); - PACK_STRUCT_FIELD(u32_t cookie); -#define DHCP_MIN_OPTIONS_LEN 68U -/** make sure user does not configure this too small */ -#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) -# undef DHCP_OPTIONS_LEN -#endif -/** allow this to be configured in lwipopts.h, but not too small */ -#if (!defined(DHCP_OPTIONS_LEN)) -/** set this to be sufficient for your options in outgoing DHCP msgs */ -# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN -#endif - PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); /** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ #define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) void dhcp_cleanup(struct netif *netif); -/** start DHCP configuration */ err_t dhcp_start(struct netif *netif); -/** enforce early lease renewal (not needed normally)*/ err_t dhcp_renew(struct netif *netif); -/** release the DHCP lease, usually called before dhcp_stop()*/ err_t dhcp_release(struct netif *netif); -/** stop DHCP configuration */ void dhcp_stop(struct netif *netif); -/** inform server of our manual IP address */ void dhcp_inform(struct netif *netif); -/** Handle a possible change in the network configuration */ void dhcp_network_changed(struct netif *netif); - -/** if enabled, check whether the offered IP address is not in use, using ARP */ #if DHCP_DOES_ARP_CHECK void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); #endif - -/** check if DHCP supplied netif->ip_addr */ u8_t dhcp_supplied_address(const struct netif *netif); - -/** to be called every minute */ +/* to be called every minute */ void dhcp_coarse_tmr(void); -/** to be called every half second */ +/* to be called every half second */ void dhcp_fine_tmr(void); -/** DHCP message item offsets and length */ -#define DHCP_OP_OFS 0 -#define DHCP_HTYPE_OFS 1 -#define DHCP_HLEN_OFS 2 -#define DHCP_HOPS_OFS 3 -#define DHCP_XID_OFS 4 -#define DHCP_SECS_OFS 8 -#define DHCP_FLAGS_OFS 10 -#define DHCP_CIADDR_OFS 12 -#define DHCP_YIADDR_OFS 16 -#define DHCP_SIADDR_OFS 20 -#define DHCP_GIADDR_OFS 24 -#define DHCP_CHADDR_OFS 28 -#define DHCP_SNAME_OFS 44 -#define DHCP_FILE_OFS 108 -#define DHCP_MSG_LEN 236 - -#define DHCP_COOKIE_OFS DHCP_MSG_LEN -#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) - -#define DHCP_CLIENT_PORT 68 -#define DHCP_SERVER_PORT 67 - -/** DHCP client states */ -#define DHCP_STATE_OFF 0 -#define DHCP_STATE_REQUESTING 1 -#define DHCP_STATE_INIT 2 -#define DHCP_STATE_REBOOTING 3 -#define DHCP_STATE_REBINDING 4 -#define DHCP_STATE_RENEWING 5 -#define DHCP_STATE_SELECTING 6 -#define DHCP_STATE_INFORMING 7 -#define DHCP_STATE_CHECKING 8 -/** not yet implemented \#define DHCP_STATE_PERMANENT 9 */ -#define DHCP_STATE_BOUND 10 -/** not yet implemented \#define DHCP_STATE_RELEASING 11 */ -#define DHCP_STATE_BACKING_OFF 12 - -/** AUTOIP cooperation flags */ -#define DHCP_AUTOIP_COOP_STATE_OFF 0 -#define DHCP_AUTOIP_COOP_STATE_ON 1 - -#define DHCP_BOOTREQUEST 1 -#define DHCP_BOOTREPLY 2 - -/** DHCP message types */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/** DHCP hardware type, currently only ethernet is supported */ -#define DHCP_HTYPE_ETH 1 - -#define DHCP_MAGIC_COOKIE 0x63825363UL - -/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ - -/** BootP options */ -#define DHCP_OPTION_PAD 0 -#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_HOSTNAME 12 -#define DHCP_OPTION_IP_TTL 23 -#define DHCP_OPTION_MTU 26 -#define DHCP_OPTION_BROADCAST 28 -#define DHCP_OPTION_TCP_TTL 37 -#define DHCP_OPTION_NTP 42 -#define DHCP_OPTION_END 255 - -/** DHCP options */ -#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ -#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ -#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ - -#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ -#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 - -#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ -#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ - -#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ -#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 - -#define DHCP_OPTION_T1 58 /* T1 renewal time */ -#define DHCP_OPTION_T2 59 /* T2 rebinding time */ -#define DHCP_OPTION_US 60 -#define DHCP_OPTION_CLIENT_ID 61 -#define DHCP_OPTION_TFTP_SERVERNAME 66 -#define DHCP_OPTION_BOOTFILE 67 - -/** possible combinations of overloading the file and sname fields with options */ -#define DHCP_OVERLOAD_NONE 0 -#define DHCP_OVERLOAD_FILE 1 -#define DHCP_OVERLOAD_SNAME 2 -#define DHCP_OVERLOAD_SNAME_FILE 3 - #if LWIP_DHCP_GET_NTP_SRV /** This function must exist, in other to add offered NTP servers to * the NTP (or SNTP) engine. diff --git a/src/include/lwip/err.h b/src/include/lwip/err.h index 81a049d8..84e528d1 100644 --- a/src/include/lwip/err.h +++ b/src/include/lwip/err.h @@ -57,44 +57,46 @@ typedef LWIP_ERR_T err_t; typedef s8_t err_t; #endif /* LWIP_ERR_T*/ -/* Definitions for error constants. */ - +/** Definitions for error constants. */ +typedef enum { /** No error, everything OK. */ -#define ERR_OK 0 + ERR_OK = 0, /** Out of memory error. */ -#define ERR_MEM -1 + ERR_MEM = -1, /** Buffer error. */ -#define ERR_BUF -2 + ERR_BUF = -2, /** Timeout. */ -#define ERR_TIMEOUT -3 + ERR_TIMEOUT = -3, /** Routing problem. */ -#define ERR_RTE -4 + ERR_RTE = -4, /** Operation in progress */ -#define ERR_INPROGRESS -5 + ERR_INPROGRESS = -5, /** Illegal value. */ -#define ERR_VAL -6 + ERR_VAL = -6, /** Operation would block. */ -#define ERR_WOULDBLOCK -7 + ERR_WOULDBLOCK = -7, /** Address in use. */ -#define ERR_USE -8 + ERR_USE = -8, /** Already connecting. */ -#define ERR_ALREADY -9 + ERR_ALREADY = -9, /** Conn already established.*/ -#define ERR_ISCONN -10 + ERR_ISCONN = -10, /** Not connected. */ -#define ERR_CONN -11 + ERR_CONN = -11, /** Low-level netif error */ -#define ERR_IF -12 + ERR_IF = -12, + +/** Connection aborted. */ + ERR_ABRT = -13, +/** Connection reset. */ + ERR_RST = -14, +/** Connection closed. */ + ERR_CLSD = -15, +/** Illegal argument. */ + ERR_ARG = -16 +} err_enum_t; #define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) -/** Connection aborted. */ -#define ERR_ABRT -13 -/** Connection reset. */ -#define ERR_RST -14 -/** Connection closed. */ -#define ERR_CLSD -15 -/** Illegal argument. */ -#define ERR_ARG -16 /** * @} @@ -106,6 +108,10 @@ extern const char *lwip_strerr(err_t err); #define lwip_strerr(x) "" #endif /* LWIP_DEBUG */ +#if !NO_SYS +int err_to_errno(err_t err); +#endif /* !NO_SYS */ + #ifdef __cplusplus } #endif diff --git a/src/include/lwip/errno.h b/src/include/lwip/errno.h new file mode 100644 index 00000000..25bc1f89 --- /dev/null +++ b/src/include/lwip/errno.h @@ -0,0 +1,193 @@ +/** + * @file + * Posix Errno defines + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERRNO_H +#define LWIP_HDR_ERRNO_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#else /* LWIP_PROVIDE_ERRNO */ + +/* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ +#ifdef LWIP_ERRNO_INCLUDE +#include LWIP_ERRNO_INCLUDE +#endif /* LWIP_ERRNO_INCLUDE */ + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERRNO_H */ diff --git a/src/include/lwip/etharp.h b/src/include/lwip/etharp.h index d23b6c23..7080a19d 100644 --- a/src/include/lwip/etharp.h +++ b/src/include/lwip/etharp.h @@ -50,7 +50,7 @@ #include "lwip/ip4_addr.h" #include "lwip/netif.h" #include "lwip/ip4.h" -#include "netif/ethernet.h" +#include "lwip/prot/ethernet.h" #ifdef __cplusplus extern "C" { @@ -58,47 +58,11 @@ extern "C" { #if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ -#ifndef ETHARP_HWADDR_LEN -#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** the ARP message, see RFC 826 ("Packet format") */ -struct etharp_hdr { - PACK_STRUCT_FIELD(u16_t hwtype); - PACK_STRUCT_FIELD(u16_t proto); - PACK_STRUCT_FLD_8(u8_t hwlen); - PACK_STRUCT_FLD_8(u8_t protolen); - PACK_STRUCT_FIELD(u16_t opcode); - PACK_STRUCT_FLD_S(struct eth_addr shwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); - PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETHARP_HDR 28 - -#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) -#define SIZEOF_ETHARP_PACKET_TX (SIZEOF_ETHARP_PACKET + SIZEOF_VLAN_HDR) -#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ -#define SIZEOF_ETHARP_PACKET_TX SIZEOF_ETHARP_PACKET -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ +#include "lwip/prot/etharp.h" /** 1 seconds period */ #define ARP_TMR_INTERVAL 1000 -/** ARP message types (opcodes) */ -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - #if ARP_QUEUEING /** struct for queueing outgoing packets for unknown address * defined here to be accessed by memp.h @@ -123,24 +87,15 @@ err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ #define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) void etharp_cleanup_netif(struct netif *netif); -void etharp_ip_input(struct netif *netif, struct pbuf *p); #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); #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ -#if LWIP_AUTOIP -err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, - const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, - const u16_t opcode); -#endif /* LWIP_AUTOIP */ - #endif /* LWIP_IPV4 && LWIP_ARP */ -void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p); +void etharp_input(struct pbuf *p, struct netif *netif); #ifdef __cplusplus } diff --git a/src/include/lwip/icmp.h b/src/include/lwip/icmp.h index 0d3652b5..490fbf74 100644 --- a/src/include/lwip/icmp.h +++ b/src/include/lwip/icmp.h @@ -41,6 +41,7 @@ #include "lwip/pbuf.h" #include "lwip/ip_addr.h" #include "lwip/netif.h" +#include "lwip/prot/icmp.h" #if LWIP_IPV6 && LWIP_ICMP6 #include "lwip/icmp6.h" @@ -50,20 +51,6 @@ extern "C" { #endif -#define ICMP_ER 0 /* echo reply */ -#define ICMP_DUR 3 /* destination unreachable */ -#define ICMP_SQ 4 /* source quench */ -#define ICMP_RD 5 /* redirect */ -#define ICMP_ECHO 8 /* echo */ -#define ICMP_TE 11 /* time exceeded */ -#define ICMP_PP 12 /* parameter problem */ -#define ICMP_TS 13 /* timestamp */ -#define ICMP_TSR 14 /* timestamp reply */ -#define ICMP_IRQ 15 /* information request */ -#define ICMP_IR 16 /* information reply */ -#define ICMP_AM 17 /* address mask request */ -#define ICMP_AMR 18 /* address mask reply */ - /** ICMP destination unreachable codes */ enum icmp_dur_type { /** net unreachable */ @@ -88,35 +75,6 @@ enum icmp_te_type { ICMP_TE_FRAG = 1 }; -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -/** This is the standard ICMP header only that the u32_t data - * is split to two u16_t like ICMP echo needs it. - * This header is also used for other ICMP types that do not - * use the data part. - */ -PACK_STRUCT_BEGIN -struct icmp_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define ICMPH_TYPE(hdr) ((hdr)->type) -#define ICMPH_CODE(hdr) ((hdr)->code) - -/** Combines type and code to an u16_t */ -#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) -#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) - - #if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ void icmp_input(struct pbuf *p, struct netif *inp); diff --git a/src/include/lwip/icmp6.h b/src/include/lwip/icmp6.h index cfa99c27..e66557d4 100644 --- a/src/include/lwip/icmp6.h +++ b/src/include/lwip/icmp6.h @@ -62,7 +62,7 @@ enum icmp6_type { /** Parameter problem */ ICMP6_TYPE_PP = 4, /** Private experimentation */ - ICMP6_TYPE_PE1 = 100, + ICMP6_TYPE_PE1 = 100, /** Private experimentation */ ICMP6_TYPE_PE2 = 101, /** Reserved for expansion of error messages */ @@ -73,7 +73,7 @@ enum icmp6_type { /** Echo reply */ ICMP6_TYPE_EREP = 129, /** Multicast listener query */ - ICMP6_TYPE_MLQ = 130, + ICMP6_TYPE_MLQ = 130, /** Multicast listener report */ ICMP6_TYPE_MLR = 131, /** Multicast listener done */ @@ -138,40 +138,6 @@ enum icmp6_pp_code { ICMP6_PP_OPTION = 2 }; -/** This is the standard ICMP6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t data); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** This is the ICMP6 header adapted for echo req/resp. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - #if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ void icmp6_input(struct pbuf *p, struct netif *inp); diff --git a/src/include/lwip/igmp.h b/src/include/lwip/igmp.h index 292e5c3b..ffd80e68 100644 --- a/src/include/lwip/igmp.h +++ b/src/include/lwip/igmp.h @@ -51,17 +51,14 @@ extern "C" { #endif - /* IGMP timer */ #define IGMP_TMR_INTERVAL 100 /* Milliseconds */ #define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) #define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) -/* MAC Filter Actions, these are passed to a netif's - * igmp_mac_filter callback function. */ -#define IGMP_DEL_MAC_FILTER 0 -#define IGMP_ADD_MAC_FILTER 1 - +/* Compatibility defines (don't use for new code) */ +#define IGMP_DEL_MAC_FILTER NETIF_DEL_MAC_FILTER +#define IGMP_ADD_MAC_FILTER NETIF_ADD_MAC_FILTER /** * igmp group structure - there is @@ -77,8 +74,6 @@ extern "C" { struct igmp_group { /** next link */ struct igmp_group *next; - /** interface on which the group is active */ - struct netif *netif; /** multicast address */ ip4_addr_t group_address; /** signifies we were the last person to report */ @@ -104,6 +99,13 @@ 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 + * 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() + */ +#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP)) + #ifdef __cplusplus } #endif diff --git a/src/include/lwip/inet.h b/src/include/lwip/inet.h index 036cd988..17edef33 100644 --- a/src/include/lwip/inet.h +++ b/src/include/lwip/inet.h @@ -134,8 +134,8 @@ extern const struct in6_addr in6addr_any; #define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) #define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) -/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ -#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) /* directly map this to the lwip internal functions */ #define inet_addr(cp) ipaddr_addr(cp) diff --git a/src/include/lwip/inet_chksum.h b/src/include/lwip/inet_chksum.h index 52d76d38..4e23d7f1 100644 --- a/src/include/lwip/inet_chksum.h +++ b/src/include/lwip/inet_chksum.h @@ -42,15 +42,9 @@ #include "lwip/pbuf.h" #include "lwip/ip_addr.h" -/** Swap the bytes in an u16_t: much like htons() for little-endian */ +/** Swap the bytes in an u16_t: much like lwip_htons() for little-endian */ #ifndef SWAP_BYTES_IN_WORD -#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) -/* little endian and PLATFORM_BYTESWAP defined */ -#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) -#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ -/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ #define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) -#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ #endif /* SWAP_BYTES_IN_WORD */ /** Split an u32_t in two u16_ts and add them up */ diff --git a/src/include/lwip/ip.h b/src/include/lwip/ip.h index 772a4c0c..0673be9b 100644 --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h @@ -34,8 +34,8 @@ * Author: Adam Dunkels * */ -#ifndef LWIP_HDR_IP_H__ -#define LWIP_HDR_IP_H__ +#ifndef LWIP_HDR_IP_H +#define LWIP_HDR_IP_H #include "lwip/opt.h" @@ -46,27 +46,16 @@ #include "lwip/netif.h" #include "lwip/ip4.h" #include "lwip/ip6.h" +#include "lwip/prot/ip.h" #ifdef __cplusplus extern "C" { #endif -#define IP_PROTO_ICMP 1 -#define IP_PROTO_IGMP 2 -#define IP_PROTO_UDP 17 -#define IP_PROTO_UDPLITE 136 -#define IP_PROTO_TCP 6 - -/** This operates on a void* by loading the first byte */ -#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) - /* This is passed as the destination address to ip_output_if (not to ip_output), meaning that an IP header already is constructed in the pbuf. This is used when TCP retransmits. */ -#ifdef IP_HDRINCL -#undef IP_HDRINCL -#endif /* IP_HDRINCL */ -#define IP_HDRINCL NULL +#define LWIP_IP_HDRINCL NULL /** pbufs passed to IP must have a ref-count of 1 as their payload pointer gets altered as the packet is passed down the stack */ @@ -230,17 +219,26 @@ extern struct ip_globals ip_data; #define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) #if LWIP_IPV4 && LWIP_IPV6 -/** Output IP packet, netif is selected by source address */ +/** + * @ingroup ip + * Output IP packet, netif is selected by source address + */ #define ip_output(p, src, dest, ttl, tos, proto) \ (IP_IS_V6(dest) ? \ ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) -/** Output IP packet to specified interface */ +/** + * @ingroup ip + * Output IP packet to specified interface + */ #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ (IP_IS_V6(dest) ? \ ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) -/** Output IP packet to interface specifying source address */ +/** + * @ingroup ip + * Output IP packet to interface specifying source address + */ #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ (IP_IS_V6(dest) ? \ ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ @@ -250,12 +248,18 @@ extern struct ip_globals ip_data; (IP_IS_V6(dest) ? \ ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) -/** Get netif for address combination. See \ref ip6_route and \ref ip4_route */ +/** + * @ingroup ip + * Get netif for address combination. See \ref ip6_route and \ref ip4_route + */ #define ip_route(src, dest) \ (IP_IS_V6(dest) ? \ ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) -/** Get netif for IP.*/ +/** + * @ingroup ip + * Get netif for IP. + */ #define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ ip4_netif_get_local_ip(netif)) @@ -310,6 +314,6 @@ err_t ip_input(struct pbuf *p, struct netif *inp); } #endif -#endif /* LWIP_HDR_IP_H__ */ +#endif /* LWIP_HDR_IP_H */ diff --git a/src/include/lwip/ip4.h b/src/include/lwip/ip4.h index c78c1194..48246ecc 100644 --- a/src/include/lwip/ip4.h +++ b/src/include/lwip/ip4.h @@ -46,6 +46,7 @@ #include "lwip/ip4_addr.h" #include "lwip/err.h" #include "lwip/netif.h" +#include "lwip/prot/ip4.h" #ifdef __cplusplus extern "C" { @@ -60,62 +61,6 @@ extern "C" { /** Currently, the function ip_output_if_opt() is only used with IGMP */ #define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) -#define IP_HLEN 20 - - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip_hdr { - /* version / header length */ - PACK_STRUCT_FLD_8(u8_t _v_hl); - /* type of service */ - PACK_STRUCT_FLD_8(u8_t _tos); - /* total length */ - PACK_STRUCT_FIELD(u16_t _len); - /* identification */ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -#define IP_RF 0x8000U /* reserved fragment flag */ -#define IP_DF 0x4000U /* don't fragment flag */ -#define IP_MF 0x2000U /* more fragments flag */ -#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ - /* time to live */ - PACK_STRUCT_FLD_8(u8_t _ttl); - /* protocol*/ - PACK_STRUCT_FLD_8(u8_t _proto); - /* checksum */ - PACK_STRUCT_FIELD(u16_t _chksum); - /* source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip4_addr_p_t src); - PACK_STRUCT_FLD_S(ip4_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IPH_V(hdr) ((hdr)->_v_hl >> 4) -#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) -#define IPH_TOS(hdr) ((hdr)->_tos) -#define IPH_LEN(hdr) ((hdr)->_len) -#define IPH_ID(hdr) ((hdr)->_id) -#define IPH_OFFSET(hdr) ((hdr)->_offset) -#define IPH_TTL(hdr) ((hdr)->_ttl) -#define IPH_PROTO(hdr) ((hdr)->_proto) -#define IPH_CHKSUM(hdr) ((hdr)->_chksum) - -#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) -#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) -#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) -#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) -#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) -#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) -#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) -#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) - #define ip_init() /* Compatibility define, no init needed. */ struct netif *ip4_route(const ip4_addr_t *dest); #if LWIP_IPV4_SRC_ROUTING diff --git a/src/include/lwip/ip4_addr.h b/src/include/lwip/ip4_addr.h index 2db8bd51..166acfab 100644 --- a/src/include/lwip/ip4_addr.h +++ b/src/include/lwip/ip4_addr.h @@ -141,7 +141,7 @@ struct netif; (u32_t)((d) & 0xff) #else /** Set an IP address given by the four byte-parts. - Little-endian version that prevents the use of htonl. */ + Little-endian version that prevents the use of lwip_htonl. */ #define IP4_ADDR(ipaddr, a,b,c,d) \ (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ ((u32_t)((c) & 0xff) << 16) | \ @@ -164,7 +164,7 @@ struct netif; (src)->addr)) /** Set complete address to zero */ #define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) -/** Set address to IPADDR_ANY (no need for htonl()) */ +/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ #define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) /** Set address to loopback address */ #define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) @@ -174,7 +174,7 @@ struct netif; * from host- to network-order. */ #define ip4_addr_set_hton(dest, src) ((dest)->addr = \ ((src) == NULL ? 0:\ - htonl((src)->addr))) + lwip_htonl((src)->addr))) /** IPv4 only: set the IP address given as an u32_t */ #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) /** IPv4 only: get the IP address as an u32_t */ diff --git a/src/include/lwip/ip4_frag.h b/src/include/lwip/ip4_frag.h index 89b9e311..ed5bf14a 100644 --- a/src/include/lwip/ip4_frag.h +++ b/src/include/lwip/ip4_frag.h @@ -73,7 +73,7 @@ struct pbuf * ip4_reass(struct pbuf *p); #endif /* IP_REASSEMBLY */ #if IP_FRAG -#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +#if !LWIP_NETIF_TX_SINGLE_PBUF #ifndef LWIP_PBUF_CUSTOM_REF_DEFINED #define LWIP_PBUF_CUSTOM_REF_DEFINED /** A custom pbuf that holds a reference to another pbuf, which is freed @@ -86,7 +86,7 @@ struct pbuf_custom_ref { struct pbuf *original; }; #endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ -#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); #endif /* IP_FRAG */ diff --git a/src/include/lwip/ip6.h b/src/include/lwip/ip6.h index 7b3fe876..099b94fb 100644 --- a/src/include/lwip/ip6.h +++ b/src/include/lwip/ip6.h @@ -46,6 +46,7 @@ #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ #include "lwip/ip6_addr.h" +#include "lwip/prot/ip6.h" #include "lwip/def.h" #include "lwip/pbuf.h" #include "lwip/netif.h" @@ -56,111 +57,6 @@ extern "C" { #endif -#define IP6_HLEN 40 - -#define IP6_NEXTH_HOPBYHOP 0 -#define IP6_NEXTH_TCP 6 -#define IP6_NEXTH_UDP 17 -#define IP6_NEXTH_ENCAPS 41 -#define IP6_NEXTH_ROUTING 43 -#define IP6_NEXTH_FRAGMENT 44 -#define IP6_NEXTH_ICMP6 58 -#define IP6_NEXTH_NONE 59 -#define IP6_NEXTH_DESTOPTS 60 -#define IP6_NEXTH_UDPLITE 136 - - -/** The IPv6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hdr { - /** version / traffic class / flow label */ - PACK_STRUCT_FIELD(u32_t _v_tc_fl); - /** payload length */ - PACK_STRUCT_FIELD(u16_t _plen); - /** next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /** hop limit */ - PACK_STRUCT_FLD_8(u8_t _hoplim); - /** source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip6_addr_p_t src); - PACK_STRUCT_FLD_S(ip6_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Hop-by-hop router alert option. */ -#define IP6_HBH_HLEN 8 -#define IP6_PAD1_OPTION 0 -#define IP6_PADN_ALERT_OPTION 1 -#define IP6_ROUTER_ALERT_OPTION 5 -#define IP6_ROUTER_ALERT_VALUE_MLD 0 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hbh_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* header length */ - PACK_STRUCT_FLD_8(u8_t _hlen); - /* router alert option type */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_type); - /* router alert option data len */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); - /* router alert option data */ - PACK_STRUCT_FIELD(u16_t _ra_opt_data); - /* PadN option type */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_type); - /* PadN option data len */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Fragment header. */ -#define IP6_FRAG_HLEN 8 -#define IP6_FRAG_OFFSET_MASK 0xfff8 -#define IP6_FRAG_MORE_FLAG 0x0001 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_frag_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* reserved */ - PACK_STRUCT_FLD_8(u8_t reserved); - /* fragment offset */ - PACK_STRUCT_FIELD(u16_t _fragment_offset); - /* fragmented packet identification */ - PACK_STRUCT_FIELD(u32_t _identification); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) -#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) -#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff) -#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen)) -#define IP6H_NEXTH(hdr) ((hdr)->_nexth) -#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) -#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) - -#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) -#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen) -#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) -#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) - - struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); err_t ip6_input(struct pbuf *p, struct netif *inp); diff --git a/src/include/lwip/ip6_addr.h b/src/include/lwip/ip6_addr.h index 665e75f2..14d0f7cf 100644 --- a/src/include/lwip/ip6_addr.h +++ b/src/include/lwip/ip6_addr.h @@ -86,7 +86,7 @@ typedef struct ip6_addr_packed ip6_addr_p_t; (u32_t)((d) & 0xff) #else /** Set an IPv6 partial address given by byte-parts. -Little-endian version, stored in network order (no htonl). */ +Little-endian version, stored in network order (no lwip_htonl). */ #define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ (ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \ ((u32_t)((c) & 0xff) << 16) | \ @@ -103,21 +103,21 @@ Little-endian version, stored in network order (no htonl). */ (ip6addr)->addr[3] = idx3; } while(0) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((htonl((ip6addr)->addr[0])) & 0xffff)) +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((htonl((ip6addr)->addr[1])) & 0xffff)) +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((htonl((ip6addr)->addr[2])) & 0xffff)) +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) /** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((htonl((ip6addr)->addr[3])) & 0xffff)) +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) /** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ #define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ @@ -136,7 +136,7 @@ Little-endian version, stored in network order (no htonl). */ (ip6addr)->addr[2] = 0; \ (ip6addr)->addr[3] = 0;}while(0) -/** Set address to ipv6 'any' (no need for htonl()) */ +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ #define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) /** Set address to ipv6 loopback address */ #define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ @@ -145,10 +145,10 @@ Little-endian version, stored in network order (no htonl). */ (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) /** Safely copy one IPv6 address to another and change byte order * from host- to network-order. */ -#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \ - (dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \ - (dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \ - (dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0) +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) /** @@ -166,7 +166,7 @@ Little-endian version, stored in network order (no htonl). */ ((addr1)->addr[2] == (addr2)->addr[2]) && \ ((addr1)->addr[3] == (addr2)->addr[3])) -#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL) +#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) #define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ ((ip6addr).addr[1] == 0) && \ @@ -193,7 +193,7 @@ Little-endian version, stored in network order (no htonl). */ #define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) #define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) #define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) -#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) #define IP6_MULTICAST_SCOPE_RESERVED 0x0 #define IP6_MULTICAST_SCOPE_RESERVED0 0x0 #define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 @@ -259,9 +259,11 @@ Little-endian version, stored in network order (no htonl). */ #define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ #define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ #define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ -#define IP6_ADDR_VALID 0x10 +#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ #define IP6_ADDR_PREFERRED 0x30 -#define IP6_ADDR_DEPRECATED 0x50 +#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ + +#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ #define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) #define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) diff --git a/src/include/lwip/ip6_frag.h b/src/include/lwip/ip6_frag.h index d625e4e5..6be27473 100644 --- a/src/include/lwip/ip6_frag.h +++ b/src/include/lwip/ip6_frag.h @@ -89,7 +89,7 @@ struct ip6_reassdata { #define ip6_reass_init() /* Compatibility define */ void ip6_reass_tmr(void); -struct pbuf * ip6_reass(struct pbuf *p); +struct pbuf *ip6_reass(struct pbuf *p); #endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ diff --git a/src/include/lwip/ip_addr.h b/src/include/lwip/ip_addr.h index d2690e8b..c1df7464 100644 --- a/src/include/lwip/ip_addr.h +++ b/src/include/lwip/ip_addr.h @@ -34,8 +34,8 @@ * Author: Adam Dunkels * */ -#ifndef LWIP_HDR_IP_ADDR_H__ -#define LWIP_HDR_IP_ADDR_H__ +#ifndef LWIP_HDR_IP_ADDR_H +#define LWIP_HDR_IP_ADDR_H #include "lwip/opt.h" #include "lwip/def.h" @@ -47,10 +47,18 @@ extern "C" { #endif -/** These are the values for ip_addr_t.type */ -#define IPADDR_TYPE_V4 0U -#define IPADDR_TYPE_V6 6U -#define IPADDR_TYPE_ANY 46U +/** @ingroup ipaddr + * IP address types for use in ip_addr_t.type member. + * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). + */ +enum lwip_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; #if LWIP_IPV4 && LWIP_IPV6 /** @@ -63,6 +71,7 @@ typedef struct _ip_addr { ip6_addr_t ip6; ip4_addr_t ip4; } u_addr; + /** @ref lwip_ip_addr_type */ u8_t type; } ip_addr_t; @@ -304,19 +313,25 @@ extern const ip_addr_t ip_addr_any; extern const ip_addr_t ip_addr_broadcast; /** - * @ingroup ipaddr - * IP_ADDR_ can be used as a fixed/const ip_addr_t - * for the IPv4 wildcard and the broadcast address + * @ingroup ip4addr + * Provided for compatibility. Use IP4_ADDR_ANY for better readability. */ -#define IP_ADDR_ANY (&ip_addr_any) -/** @ingroup ipaddr */ -#define IP_ADDR_BROADCAST (&ip_addr_broadcast) +#define IP_ADDR_ANY IP4_ADDR_ANY /** * @ingroup ip4addr - * IP4_ADDR_ can be used as a fixed/const ip4_addr_t + * Can be used as a fixed/const ip_addr_t + * for the IPv4 wildcard and the broadcast address + */ +#define IP4_ADDR_ANY (&ip_addr_any) +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip4_addr_t * for the wildcard and the broadcast address */ -#define IP4_ADDR_ANY (ip_2_ip4(&ip_addr_any)) +#define IP4_ADDR_ANY4 (ip_2_ip4(&ip_addr_any)) + +/** @ingroup ip4addr */ +#define IP_ADDR_BROADCAST (&ip_addr_broadcast) /** @ingroup ip4addr */ #define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) @@ -357,4 +372,4 @@ extern const ip_addr_t ip6_addr_any; } #endif -#endif /* LWIP_HDR_IP_ADDR_H__ */ +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/src/include/lwip/memp.h b/src/include/lwip/memp.h index 8a555c89..68fcd991 100644 --- a/src/include/lwip/memp.h +++ b/src/include/lwip/memp.h @@ -58,6 +58,12 @@ typedef enum { extern const struct memp_desc* const memp_pools[MEMP_MAX]; +/** + * @ingroup mempool + * Declare prototype for private memory pool if it is used in multiple files + */ +#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name + #if MEMP_MEM_MALLOC #define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ @@ -70,12 +76,6 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX]; #else /* MEMP_MEM_MALLOC */ -/** - * @ingroup mempool - * Declare prototype for private memory pool if it is used in multiple files - */ -#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name - /** * @ingroup mempool * Declare a private memory pool diff --git a/src/include/lwip/mld6.h b/src/include/lwip/mld6.h index 6fcd110f..7fa0797f 100644 --- a/src/include/lwip/mld6.h +++ b/src/include/lwip/mld6.h @@ -50,7 +50,6 @@ #include "lwip/pbuf.h" #include "lwip/netif.h" - #ifdef __cplusplus extern "C" { #endif @@ -59,8 +58,6 @@ extern "C" { struct mld_group { /** next link */ struct mld_group *next; - /** interface on which the group is active */ - struct netif *netif; /** multicast address */ ip6_addr_t group_address; /** signifies we were the last person to report */ @@ -73,33 +70,8 @@ struct mld_group { u8_t use; }; -/** Multicast listener report/query/done message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mld_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t max_resp_delay); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - #define MLD6_TMR_INTERVAL 100 /* Milliseconds */ -/* MAC Filter Actions, these are passed to a netif's - * mld_mac_filter callback function. */ -#define MLD6_DEL_MAC_FILTER 0 -#define MLD6_ADD_MAC_FILTER 1 - - err_t mld6_stop(struct netif *netif); void mld6_report_groups(struct netif *netif); void mld6_tmr(void); @@ -110,6 +82,13 @@ err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); +/** @ingroup mld6 + * Get list head of MLD6 groups for netif. + * 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() + */ +#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6)) #ifdef __cplusplus } diff --git a/src/include/lwip/nd6.h b/src/include/lwip/nd6.h index 5e096517..e4715ad3 100644 --- a/src/include/lwip/nd6.h +++ b/src/include/lwip/nd6.h @@ -61,7 +61,7 @@ extern "C" { /** Struct for tables. */ struct nd6_neighbor_cache_entry { ip6_addr_t next_hop_address; - struct netif * netif; + struct netif *netif; u8_t lladdr[NETIF_MAX_HWADDR_LEN]; /*u32_t pmtu;*/ #if LWIP_ND6_QUEUEING @@ -74,10 +74,10 @@ struct nd6_neighbor_cache_entry { u8_t state; u8_t isrouter; union { - u32_t reachable_time; - u32_t delay_time; + u32_t reachable_time; /* in ms since value may originate from network packet */ + u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */ u32_t probes_sent; - u32_t stale_time; + u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */ } counter; }; @@ -90,8 +90,8 @@ struct nd6_destination_cache_entry { struct nd6_prefix_list_entry { ip6_addr_t prefix; - struct netif * netif; - u32_t invalidation_timer; + struct netif *netif; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ #if LWIP_IPV6_AUTOCONFIG u8_t flags; #define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 @@ -101,12 +101,11 @@ struct nd6_prefix_list_entry { }; struct nd6_router_list_entry { - struct nd6_neighbor_cache_entry * neighbor_entry; - u32_t invalidation_timer; + struct nd6_neighbor_cache_entry *neighbor_entry; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ u8_t flags; }; - enum nd6_neighbor_cache_entry_state { ND6_NO_ENTRY = 0, ND6_INCOMPLETE, @@ -126,208 +125,6 @@ struct nd6_q_entry { }; #endif /* LWIP_ND6_QUEUEING */ -/** Neighbor solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ns_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Neighbor advertisement message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct na_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FLD_8(u8_t reserved[3]); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define ND6_FLAG_ROUTER (0x80) -#define ND6_FLAG_SOLICITED (0x40) -#define ND6_FLAG_OVERRIDE (0x20) - -/** Router solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct rs_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Router advertisement message header. */ -#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) -#define ND6_RA_FLAG_OTHER_CONFIG (0x40) -#define ND6_RA_FLAG_HOME_AGENT (0x20) -#define ND6_RA_PREFERENCE_MASK (0x18) -#define ND6_RA_PREFERENCE_HIGH (0x08) -#define ND6_RA_PREFERENCE_MEDIUM (0x00) -#define ND6_RA_PREFERENCE_LOW (0x18) -#define ND6_RA_PREFERENCE_DISABLED (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ra_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t current_hop_limit); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u16_t router_lifetime); - PACK_STRUCT_FIELD(u32_t reachable_time); - PACK_STRUCT_FIELD(u32_t retrans_timer); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirect message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirect_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Link-layer address option. */ -#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) -#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct lladdr_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Prefix information option. */ -#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) -#define ND6_PREFIX_FLAG_ON_LINK (0x80) -#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) -#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) -#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct prefix_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u32_t valid_lifetime); - PACK_STRUCT_FIELD(u32_t preferred_lifetime); - PACK_STRUCT_FLD_8(u8_t reserved2[3]); - PACK_STRUCT_FLD_8(u8_t site_prefix_length); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirected header option. */ -#define ND6_OPTION_TYPE_REDIR_HDR (0x04) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirected_header_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t reserved[6]); - /* Portion of redirected packet follows. */ - /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** MTU option. */ -#define ND6_OPTION_TYPE_MTU (0x05) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mtu_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FIELD(u32_t mtu); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Route information option. */ -#define ND6_OPTION_TYPE_ROUTE_INFO (24) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct route_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t preference); - PACK_STRUCT_FIELD(u32_t route_lifetime); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - /** 1 second period */ #define ND6_TMR_INTERVAL 1000 @@ -344,14 +141,14 @@ extern u32_t retrans_timer; void nd6_tmr(void); void nd6_input(struct pbuf *p, struct netif *inp); -s8_t nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif); -s8_t nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif); -u16_t nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif); -err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p); +s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); +s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); +u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif); +err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *p); #if LWIP_ND6_TCP_REACHABILITY_HINTS -void nd6_reachability_hint(const ip6_addr_t * ip6addr); +void nd6_reachability_hint(const ip6_addr_t *ip6addr); #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ -void nd6_cleanup_netif(struct netif * netif); +void nd6_cleanup_netif(struct netif *netif); #ifdef __cplusplus } diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index 8903a563..67a2d24d 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -49,16 +49,6 @@ #include "lwip/pbuf.h" #include "lwip/stats.h" -#if LWIP_DHCP -struct dhcp; -#endif -#if LWIP_AUTOIP -struct autoip; -#endif -#if LWIP_IPV6_DHCP6 -struct dhcp6; -#endif /* LWIP_IPV6_DHCP6 */ - #ifdef __cplusplus extern "C" { #endif @@ -78,7 +68,7 @@ extern "C" { * @ingroup netif * @{ */ - + /** Whether the network interface is 'up'. This is * a software flag used to control whether this network * interface is enabled and processes traffic. @@ -114,6 +104,23 @@ extern "C" { * @} */ +enum lwip_internal_netif_client_data_index +{ +#if LWIP_DHCP + LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, +#endif +#if LWIP_AUTOIP + LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, +#endif +#if LWIP_IGMP + LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, +#endif +#if LWIP_IPV6_MLD + LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, +#endif + LWIP_NETIF_CLIENT_DATA_INDEX_MAX +}; + #if LWIP_CHECKSUM_CTRL_PER_NETIF #define NETIF_CHECKSUM_GEN_IP 0x0001 #define NETIF_CHECKSUM_GEN_UDP 0x0002 @@ -131,6 +138,15 @@ extern "C" { struct netif; +/** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or + * mld_mac_filter callback function. */ +enum netif_mac_filter_action { + /** Delete a filter entry */ + NETIF_DEL_MAC_FILTER = 0, + /** Add a filter entry */ + NETIF_ADD_MAC_FILTER = 1 +}; + /** Function prototype for netif init functions. Set up flags and output/linkoutput * callback functions in this function. * @@ -183,14 +199,26 @@ typedef void (*netif_status_callback_fn)(struct netif *netif); #if LWIP_IPV4 && LWIP_IGMP /** Function prototype for netif igmp_mac_filter functions */ typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, - const ip4_addr_t *group, u8_t action); + const ip4_addr_t *group, enum netif_mac_filter_action action); #endif /* LWIP_IPV4 && LWIP_IGMP */ #if LWIP_IPV6 && LWIP_IPV6_MLD /** Function prototype for netif mld_mac_filter functions */ typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, - const ip6_addr_t *group, u8_t action); + const ip6_addr_t *group, enum netif_mac_filter_action action); #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0) +u8_t netif_alloc_client_data_id(void); +/** @ingroup netif_cd + * Set client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data) +/** @ingroup netif_cd + * Get client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_get_client_data(netif, id) (netif)->client_data[(id)] +#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */ + /** Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ @@ -217,17 +245,19 @@ struct netif { #if LWIP_IPV4 /** This function is called by the IP module when it wants * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. */ + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually etharp_output() */ netif_output_fn output; #endif /* LWIP_IPV4 */ - /** This function is called by the ARP module when it wants + /** This function is called by ethernet_output() when it wants * to send a packet on the interface. This function outputs * the pbuf as-is on the link medium. */ netif_linkoutput_fn linkoutput; #if LWIP_IPV6 /** This function is called by the IPv6 module when it wants * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. */ + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually ethip6_output() */ netif_output_ip6_fn output_ip6; #endif /* LWIP_IPV6 */ #if LWIP_NETIF_STATUS_CALLBACK @@ -247,13 +277,8 @@ struct netif { /** This field can be set by the device driver and could point * to state information for the device. */ void *state; -#if LWIP_DHCP - /** the DHCP client state information for this netif */ - struct dhcp *dhcp; -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - /** the AutoIP client state information for this netif */ - struct autoip *autoip; +#ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; #endif #if LWIP_IPV6_AUTOCONFIG /** is this netif enabled for IPv6 autoconfiguration */ @@ -263,10 +288,6 @@ struct netif { /** Number of Router Solicitation messages that remain to be sent. */ u8_t rs_count; #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_IPV6_DHCP6 - /** the DHCPv6 client state information for this netif */ - struct dhcp6 *dhcp6; -#endif /* LWIP_IPV6_DHCP6 */ #if LWIP_NETIF_HOSTNAME /* the hostname for this netif, NULL is a valid value */ const char* hostname; @@ -358,11 +379,17 @@ void netif_set_default(struct netif *netif); void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); +/** @ingroup netif_ip4 */ #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) +/** @ingroup netif_ip4 */ #define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) +/** @ingroup netif_ip4 */ #define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) +/** @ingroup netif_ip4 */ #define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) +/** @ingroup netif_ip4 */ #define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask)) +/** @ingroup netif_ip4 */ #define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) #endif /* LWIP_IPV4 */ @@ -390,16 +417,20 @@ void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_ #endif /* LWIP_NETIF_LINK_CALLBACK */ #if LWIP_NETIF_HOSTNAME +/** @ingroup netif */ #define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +/** @ingroup netif */ #define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) #endif /* LWIP_NETIF_HOSTNAME */ #if LWIP_IGMP +/** @ingroup netif */ #define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) #define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) #endif /* LWIP_IGMP */ #if LWIP_IPV6 && LWIP_IPV6_MLD +/** @ingroup netif */ #define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) #define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) #define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) @@ -416,13 +447,14 @@ void netif_poll_all(void); err_t netif_input(struct pbuf *p, struct netif *inp); #if LWIP_IPV6 -/** @ingroup netif */ +/** @ingroup netif_ip6 */ #define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) -/** @ingroup netif */ +/** @ingroup netif_ip6 */ #define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) -#define netif_ip6_addr_set(netif, i, addr6) do { ip6_addr_set(ip_2_ip6(&((netif)->ip6_addr[i])), addr6); IP_SET_TYPE_VAL((netif)->ip6_addr[i], IPADDR_TYPE_V6); } while(0) +void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); +void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); #define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) -#define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[i] = (state)) +void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index b37124ce..0db03b50 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -36,8 +36,8 @@ * */ -/* - * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - +/* + * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - * without this, doxygen does not see the actual #define */ @@ -51,7 +51,7 @@ #include "lwipopts.h" #include "lwip/debug.h" -/** +/** * @defgroup lwip_opts Options (lwipopts.h) * @ingroup lwip * @@ -401,9 +401,9 @@ /** * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent * (fragments, not whole packets!). - * This is only used with IP_FRAG_USES_STATIC_BUF==0 and - * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs - * where the packet is not yet sent when netif->output returns. + * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 + * with DMA-enabled MACs where the packet is not yet sent when netif->output + * returns. */ #if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ #define MEMP_NUM_FRAG_PBUF 15 @@ -576,20 +576,6 @@ #define ARP_QUEUE_LEN 3 #endif -/** - * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be - * updated with the source MAC and IP addresses supplied in the packet. - * You may want to disable this if you do not trust LAN peers to have the - * correct addresses, or as a limited approach to attempt to handle - * spoofing. If disabled, lwIP will need to make a new ARP request if - * the peer is not already in the ARP table, adding a little latency. - * The peer *is* in the ARP table if it requested our address before. - * Also notice that this slows down input processing of every IP packet! - */ -#if !defined ETHARP_TRUST_IP_MAC || defined __DOXYGEN__ -#define ETHARP_TRUST_IP_MAC 0 -#endif - /** * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and @@ -719,25 +705,6 @@ #define IP_REASS_MAX_PBUFS 10 #endif -/** - * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP - * fragmentation. Otherwise pbufs are allocated and reference the original - * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, - * new PBUF_RAM pbufs are used for fragments). - * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! - */ -#if !defined IP_FRAG_USES_STATIC_BUF || defined __DOXYGEN__ -#define IP_FRAG_USES_STATIC_BUF 0 -#endif - -/** - * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer - * (requires IP_FRAG_USES_STATIC_BUF==1) - */ -#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) || defined __DOXYGEN__ -#define IP_FRAG_MAX_MTU 1500 -#endif - /** * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. */ @@ -1011,7 +978,7 @@ * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP */ #if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ -#define LWIP_MULTICAST_TX_OPTIONS LWIP_IGMP +#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) #endif /** * @} @@ -1249,7 +1216,7 @@ /** * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. */ #if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ #define TCP_OOSEQ_MAX_BYTES 0 @@ -1257,7 +1224,7 @@ /** * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. */ #if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ #define TCP_OOSEQ_MAX_PBUFS 0 @@ -1325,6 +1292,13 @@ #if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ #define LWIP_EVENT_API 0 #define LWIP_CALLBACK_API 1 +#else +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#endif +#ifndef LWIP_CALLBACK_API +#define LWIP_CALLBACK_API 0 +#endif #endif /** @@ -1359,7 +1333,7 @@ * Ethernet. */ #if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ -#if defined LWIP_HOOK_VLAN_SET || 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) @@ -1458,6 +1432,14 @@ #if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ #define LWIP_NETIF_TX_SINGLE_PBUF 0 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store + * data in client_data member array of struct netif. + */ +#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ +#define LWIP_NUM_NETIF_CLIENT_DATA 0 +#endif /** * @} */ @@ -2199,7 +2181,7 @@ #endif /** - * LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts. + * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. */ #if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ #define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 @@ -2493,18 +2475,25 @@ #endif /** - * LWIP_HOOK_VLAN_SET(netif, eth_hdr, vlan_hdr): - * - called from etharp_raw() and etharp_send_ip() if VLAN support is enabled + * 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 + * Signature: 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 + * Arguments: * - netif: struct netif that the packet will be sent through - * - eth_hdr: struct eth_hdr of the packet - * - vlan_hdr: struct eth_vlan_hdr of the packet + * - 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 + * + * * Return values: - * - 0: Packet shall not contain VLAN header. - * - != 0: Packet shall contain VLAN header. - * Hook can be used to set prio_vid field of vlan_hdr. + * - <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. */ #ifdef __DOXYGEN__ -#define LWIP_HOOK_VLAN_SET(netif, eth_hdr, vlan_hdr) +#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) #endif /** @@ -2514,6 +2503,16 @@ #ifdef __DOXYGEN__ #define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) #endif + +/** + * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): + * Called from ethernet_input() when an unknown eth type is encountered. + * Return ERR_OK if packet is accepted, any error code otherwise. + * Payload points to ethernet header! + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) +#endif /** * @} */ diff --git a/src/include/lwip/pbuf.h b/src/include/lwip/pbuf.h index a3a761f5..90610461 100644 --- a/src/include/lwip/pbuf.h +++ b/src/include/lwip/pbuf.h @@ -52,7 +52,7 @@ extern "C" { * Currently, the pbuf_custom code is only needed for one specific configuration * of IP_FRAG, unless required by external driver/application code. */ #ifndef LWIP_SUPPORT_CUSTOM_PBUF -#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) +#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) #endif /* @todo: We need a mechanism to prevent wasting memory in every pbuf @@ -65,11 +65,32 @@ extern "C" { #define PBUF_IP_HLEN 20 #endif +/** + * @ingroup pbuf + * Enumeration of pbuf layers + */ typedef enum { + /** Includes spare room for transport layer header, e.g. UDP header. + * Use this if you intend to pass the pbuf to functions like udp_send(). + */ PBUF_TRANSPORT, + /** Includes spare room for IP header. + * Use this if you intend to pass the pbuf to functions like raw_send(). + */ PBUF_IP, + /** Includes spare room for link layer header (ethernet header). + * Use this if you intend to pass the pbuf to functions like ethernet_output(). + * @see PBUF_LINK_HLEN + */ PBUF_LINK, + /** Includes spare room for additional encapsulation header before ethernet + * headers (e.g. 802.11). + * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). + * @see PBUF_LINK_ENCAPSULATION_HLEN + */ PBUF_RAW_TX, + /** Use this for input packets in a netif driver when calling netif->input() + * in the most common case - ethernet-layer netif driver. */ PBUF_RAW } pbuf_layer; @@ -80,9 +101,10 @@ typedef enum { typedef enum { /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload are allocated in one piece of contiguous memory (so the first payload byte - can be calculated from struct pbuf) + can be calculated from struct pbuf). pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might - change in future versions) */ + change in future versions). + This should be used for all OUTGOING packets (TX).*/ PBUF_RAM, /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in totally different memory areas. Since it points to ROM, payload does not @@ -95,7 +117,9 @@ typedef enum { /** pbuf payload refers to RAM. This one comes from a pool and should be used for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct pbuf and its payload are allocated in one piece of contiguous memory (so - the first payload byte can be calculated from struct pbuf) */ + the first payload byte can be calculated from struct pbuf). + Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, + you are unable to receive TCP acks! */ PBUF_POOL } pbuf_type; @@ -207,12 +231,12 @@ u8_t pbuf_header(struct pbuf *p, s16_t header_size); u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); void pbuf_ref(struct pbuf *p); u8_t pbuf_free(struct pbuf *p); -u8_t pbuf_clen(struct pbuf *p); +u16_t pbuf_clen(const struct pbuf *p); void pbuf_cat(struct pbuf *head, struct pbuf *tail); void pbuf_chain(struct pbuf *head, struct pbuf *tail); struct pbuf *pbuf_dechain(struct pbuf *p); -err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); -u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); +u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); @@ -225,11 +249,12 @@ err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); #endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ -u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +u8_t pbuf_get_at(const struct pbuf* p, u16_t offset); +int pbuf_try_get_at(const struct pbuf* p, u16_t offset); void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); -u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); -u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); -u16_t pbuf_strstr(struct pbuf* p, const char* substr); +u16_t pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(const struct pbuf* p, const char* substr); #ifdef __cplusplus } diff --git a/src/include/lwip/priv/memp_std.h b/src/include/lwip/priv/memp_std.h index ee3e2537..ce9fd500 100644 --- a/src/include/lwip/priv/memp_std.h +++ b/src/include/lwip/priv/memp_std.h @@ -55,9 +55,9 @@ LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), #if LWIP_IPV4 && IP_REASSEMBLY LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") #endif /* LWIP_IPV4 && IP_REASSEMBLY */ -#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) +#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") -#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */ #if LWIP_NETCONN || LWIP_SOCKET LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") diff --git a/src/include/lwip/priv/tcp_priv.h b/src/include/lwip/priv/tcp_priv.h index 957408d8..51747e0f 100644 --- a/src/include/lwip/priv/tcp_priv.h +++ b/src/include/lwip/priv/tcp_priv.h @@ -49,6 +49,7 @@ #include "lwip/err.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" +#include "lwip/prot/tcp.h" #ifdef __cplusplus extern "C" { @@ -111,19 +112,6 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb); #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) #endif #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) -#define TCP_FIN 0x01U -#define TCP_SYN 0x02U -#define TCP_RST 0x04U -#define TCP_PSH 0x08U -#define TCP_ACK 0x10U -#define TCP_URG 0x20U -#define TCP_ECE 0x40U -#define TCP_CWR 0x80U - -#define TCP_FLAGS 0x3fU - -/* Length of the TCP header, excluding options. */ -#define TCP_HLEN 20 #ifndef TCP_TMR_INTERVAL #define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ @@ -161,38 +149,6 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb); #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ -/* Fields are (of course) in network byte order. - * Some fields are converted to host byte order in tcp_input(). - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct tcp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); - PACK_STRUCT_FIELD(u32_t seqno); - PACK_STRUCT_FIELD(u32_t ackno); - PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); - PACK_STRUCT_FIELD(u16_t wnd); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t urgp); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define TCPH_HDRLEN(phdr) ((u16_t)(ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) -#define TCPH_FLAGS(phdr) ((u16_t)(ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) - -#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) -#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | htons(flags)) -#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) - -#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) -#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~htons(flags)) - #define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) /** Flags used on input processing, not on pcb->flags @@ -334,7 +290,7 @@ struct tcp_seg { (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) /** This returns a TCP header option for MSS in an u32_t */ -#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) +#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF)) #if LWIP_WND_SCALE #define TCPWNDSIZE_F U32_F @@ -537,9 +493,7 @@ s16_t tcp_pcbs_sane(void); * that a timer is needed (i.e. active- or time-wait-pcb found). */ void tcp_timer_needed(void); -#if LWIP_IPV4 -void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr); -#endif /* LWIP_IPV4 */ +void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); #ifdef __cplusplus } diff --git a/src/include/lwip/priv/tcpip_priv.h b/src/include/lwip/priv/tcpip_priv.h index d9fe37ae..630efb14 100644 --- a/src/include/lwip/priv/tcpip_priv.h +++ b/src/include/lwip/priv/tcpip_priv.h @@ -48,7 +48,7 @@ #ifdef __cplusplus extern "C" { #endif - + struct pbuf; struct netif; @@ -69,7 +69,7 @@ struct netif; } while(0) #define API_VAR_FREE(pool, name) memp_free(pool, name) #define API_VAR_FREE_POOL(pool, name) LWIP_MEMPOOL_FREE(pool, name) -#define API_EXPR_REF(expr) &(expr) +#define API_EXPR_REF(expr) (&(expr)) #if LWIP_NETCONN_SEM_PER_THREAD #define API_EXPR_REF_SEM(expr) (expr) #else @@ -87,7 +87,7 @@ struct netif; #define API_VAR_FREE_POOL(pool, name) #define API_EXPR_REF(expr) expr #define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) -#define API_EXPR_DEREF(expr) *(expr) +#define API_EXPR_DEREF(expr) (*(expr)) #define API_MSG_M_DEF(m) *m #define API_MSG_M_DEF_C(t, m) const t * m #endif /* LWIP_MPU_COMPATIBLE */ @@ -112,10 +112,10 @@ enum tcpip_msg_type { TCPIP_MSG_API, TCPIP_MSG_API_CALL, TCPIP_MSG_INPKT, -#if LWIP_TCPIP_TIMEOUT +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS TCPIP_MSG_TIMEOUT, TCPIP_MSG_UNTIMEOUT, -#endif /* LWIP_TCPIP_TIMEOUT */ +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ TCPIP_MSG_CALLBACK, TCPIP_MSG_CALLBACK_STATIC }; @@ -141,13 +141,13 @@ struct tcpip_msg { tcpip_callback_fn function; void *ctx; } cb; -#if LWIP_TCPIP_TIMEOUT +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS struct { u32_t msecs; sys_timeout_handler h; void *arg; } tmo; -#endif /* LWIP_TCPIP_TIMEOUT */ +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ } msg; }; diff --git a/src/include/lwip/prot/autoip.h b/src/include/lwip/prot/autoip.h new file mode 100644 index 00000000..fd3af8a9 --- /dev/null +++ b/src/include/lwip/prot/autoip.h @@ -0,0 +1,78 @@ +/** + * @file + * AutoIP protocol definitions + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + */ + +#ifndef LWIP_HDR_PROT_AUTOIP_H +#define LWIP_HDR_PROT_AUTOIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +typedef enum { + AUTOIP_STATE_OFF = 0, + AUTOIP_STATE_PROBING = 1, + AUTOIP_STATE_ANNOUNCING = 2, + AUTOIP_STATE_BOUND = 3 +} autoip_state_enum_t; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_AUTOIP_H */ diff --git a/src/include/lwip/prot/dhcp.h b/src/include/lwip/prot/dhcp.h new file mode 100644 index 00000000..112953cb --- /dev/null +++ b/src/include/lwip/prot/dhcp.h @@ -0,0 +1,183 @@ +/** + * @file + * DHCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_PROT_DHCP_H +#define LWIP_HDR_PROT_DHCP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + + + /* DHCP message item offsets and length */ +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_OFS 44U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_OFS 108U +#define DHCP_FILE_LEN 128U +#define DHCP_MSG_LEN 236U +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +/* DHCP client states */ +typedef enum { + DHCP_STATE_OFF = 0, + DHCP_STATE_REQUESTING = 1, + DHCP_STATE_INIT = 2, + DHCP_STATE_REBOOTING = 3, + DHCP_STATE_REBINDING = 4, + DHCP_STATE_RENEWING = 5, + DHCP_STATE_SELECTING = 6, + DHCP_STATE_INFORMING = 7, + DHCP_STATE_CHECKING = 8, + DHCP_STATE_PERMANENT = 9, /* not yet implemented */ + DHCP_STATE_BOUND = 10, + DHCP_STATE_RELEASING = 11, /* not yet implemented */ + DHCP_STATE_BACKING_OFF = 12 +} dhcp_state_enum_t; + +/* DHCP op codes */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/* BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_NTP 42 +#define DHCP_OPTION_END 255 + +/* DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/* possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + + +#ifdef __cplusplus +} +#endif + +#endif /*LWIP_HDR_PROT_DHCP_H*/ diff --git a/src/include/lwip/prot/dns.h b/src/include/lwip/prot/dns.h new file mode 100644 index 00000000..0a99ab0c --- /dev/null +++ b/src/include/lwip/prot/dns.h @@ -0,0 +1,122 @@ +/** + * @file + * DNS - host name to IP address resolver. + */ + +/* + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + * + * security fixes and more by Simon Goldschmidt + * + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_PROT_DNS_H +#define LWIP_HDR_PROT_DNS_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/* DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ +#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ +#define DNS_RRTYPE_SRV 33 /* service location */ +#define DNS_RRTYPE_ANY 255 /* any type */ + +/* DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_ANY 255 /* any class */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FLD_8(u8_t flags1); + PACK_STRUCT_FLD_8(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_DNS_H */ diff --git a/src/include/lwip/prot/etharp.h b/src/include/lwip/prot/etharp.h new file mode 100644 index 00000000..ec78305b --- /dev/null +++ b/src/include/lwip/prot/etharp.h @@ -0,0 +1,91 @@ +/** + * @file + * ARP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHARP_H +#define LWIP_HDR_PROT_ETHARP_H + +#include "lwip/arch.h" +#include "lwip/prot/ethernet.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FLD_8(u8_t hwlen); + PACK_STRUCT_FLD_8(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FLD_S(struct eth_addr shwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); + PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 + +/* ARP hwtype values */ +enum etharp_hwtype { + HWTYPE_ETHERNET = 1 + /* others not used */ +}; + +/* ARP message types (opcodes) */ +enum etharp_opcode { + ARP_REQUEST = 1, + ARP_REPLY = 2 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHARP_H */ diff --git a/src/include/lwip/prot/ethernet.h b/src/include/lwip/prot/ethernet.h new file mode 100644 index 00000000..e4baa29d --- /dev/null +++ b/src/include/lwip/prot/ethernet.h @@ -0,0 +1,170 @@ +/** + * @file + * Ethernet protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHERNET_H +#define LWIP_HDR_PROT_ETHERNET_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETH_HWADDR_LEN +#ifdef ETHARP_HWADDR_LEN +#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ +#else +#define ETH_HWADDR_LEN 6 +#endif +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) + +/** + * @ingroup ethernet + * A list of often ethtypes (although lwIP does not use all of them): */ +enum eth_type { + /** Internet protocol v4 */ + ETHTYPE_IP = 0x0800U, + /** Address resolution protocol */ + ETHTYPE_ARP = 0x0806U, + /** Wake on lan */ + ETHTYPE_WOL = 0x0842U, + /** RARP */ + ETHTYPE_RARP = 0x8035U, + /** Virtual local area network */ + ETHTYPE_VLAN = 0x8100U, + /** Internet protocol v6 */ + ETHTYPE_IPV6 = 0x86DDU, + /** PPP Over Ethernet Discovery Stage */ + ETHTYPE_PPPOEDISC = 0x8863U, + /** PPP Over Ethernet Session Stage */ + ETHTYPE_PPPOE = 0x8864U, + /** Jumbo Frames */ + ETHTYPE_JUMBO = 0x8870U, + /** Process field network */ + ETHTYPE_PROFINET = 0x8892U, + /** Ethernet for control automation technology */ + ETHTYPE_ETHERCAT = 0x88A4U, + /** Link layer discovery protocol */ + ETHTYPE_LLDP = 0x88CCU, + /** Serial real-time communication system */ + ETHTYPE_SERCOS = 0x88CDU, + /** Media redundancy protocol */ + ETHTYPE_MRP = 0x88E3U, + /** Precision time protocol */ + ETHTYPE_PTP = 0x88F7U, + /** Q-in-Q, 802.1ad */ + ETHTYPE_QINQ = 0x9100U +}; + +/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ +#define LL_IP4_MULTICAST_ADDR_0 0x01 +#define LL_IP4_MULTICAST_ADDR_1 0x00 +#define LL_IP4_MULTICAST_ADDR_2 0x5e + +/** IPv6 multicast uses this prefix */ +#define LL_IP6_MULTICAST_ADDR_0 0x33 +#define LL_IP6_MULTICAST_ADDR_1 0x33 + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHERNET_H */ diff --git a/src/include/lwip/prot/icmp.h b/src/include/lwip/prot/icmp.h new file mode 100644 index 00000000..7d19385c --- /dev/null +++ b/src/include/lwip/prot/icmp.h @@ -0,0 +1,91 @@ +/** + * @file + * ICMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP_H +#define LWIP_HDR_PROT_ICMP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ +#define ICMP_AM 17 /* address mask request */ +#define ICMP_AMR 18 /* address mask reply */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Compatibility defines, old versions used to combine type and code to an u16_t */ +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP_H */ diff --git a/src/include/lwip/prot/icmp6.h b/src/include/lwip/prot/icmp6.h new file mode 100644 index 00000000..a0a713ba --- /dev/null +++ b/src/include/lwip/prot/icmp6.h @@ -0,0 +1,83 @@ +/** + * @file + * ICMP6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP6_H +#define LWIP_HDR_PROT_ICMP6_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP6_H */ diff --git a/src/include/lwip/prot/igmp.h b/src/include/lwip/prot/igmp.h new file mode 100644 index 00000000..d60cb31e --- /dev/null +++ b/src/include/lwip/prot/igmp.h @@ -0,0 +1,90 @@ +/** + * @file + * IGMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IGMP_H +#define LWIP_HDR_PROT_IGMP_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FLD_8(u8_t igmp_msgtype); + PACK_STRUCT_FLD_8(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IGMP_H */ diff --git a/src/include/lwip/prot/ip.h b/src/include/lwip/prot/ip.h new file mode 100644 index 00000000..bbfae367 --- /dev/null +++ b/src/include/lwip/prot/ip.h @@ -0,0 +1,51 @@ +/** + * @file + * IP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP_H +#define LWIP_HDR_PROT_IP_H + +#include "lwip/arch.h" + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/** This operates on a void* by loading the first byte */ +#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) + +#endif /* LWIP_HDR_PROT_IP_H */ diff --git a/src/include/lwip/prot/ip4.h b/src/include/lwip/prot/ip4.h new file mode 100644 index 00000000..c3c34038 --- /dev/null +++ b/src/include/lwip/prot/ip4.h @@ -0,0 +1,111 @@ +/** + * @file + * IPv4 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP4_H +#define LWIP_HDR_PROT_IP4_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ +#define IP_HLEN 20 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/* The IPv4 header */ +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FLD_8(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FLD_8(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* don't fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FLD_8(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FLD_8(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip4_addr_p_t src); + PACK_STRUCT_FLD_S(ip4_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Macros to get struct ip_hdr fields: */ +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +/* Macros to set struct ip_hdr fields: */ +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP4_H */ diff --git a/src/include/lwip/prot/ip6.h b/src/include/lwip/prot/ip6.h new file mode 100644 index 00000000..4e3ca37d --- /dev/null +++ b/src/include/lwip/prot/ip6.h @@ -0,0 +1,154 @@ +/** + * @file + * IPv6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP6_H +#define LWIP_HDR_PROT_IP6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + +/** The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /** version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /** payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /** next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /** hop limit */ + PACK_STRUCT_FLD_8(u8_t _hoplim); + /** source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip6_addr_p_t src); + PACK_STRUCT_FLD_S(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* header length */ + PACK_STRUCT_FLD_8(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FLD_8(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP6_H */ diff --git a/src/include/lwip/prot/mld6.h b/src/include/lwip/prot/mld6.h new file mode 100644 index 00000000..2664829b --- /dev/null +++ b/src/include/lwip/prot/mld6.h @@ -0,0 +1,70 @@ +/** + * @file + * MLD6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_MLD6_H +#define LWIP_HDR_PROT_MLD6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_MLD6_H */ diff --git a/src/include/lwip/prot/nd6.h b/src/include/lwip/prot/nd6.h new file mode 100644 index 00000000..eae3d28e --- /dev/null +++ b/src/include/lwip/prot/nd6.h @@ -0,0 +1,253 @@ +/** + * @file + * ND6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ND6_H +#define LWIP_HDR_PROT_ND6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FLD_8(u8_t reserved[3]); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t current_hop_limit); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FLD_8(u8_t reserved2[3]); + PACK_STRUCT_FLD_8(u8_t site_prefix_length); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ND6_H */ diff --git a/src/include/lwip/prot/tcp.h b/src/include/lwip/prot/tcp.h new file mode 100644 index 00000000..c2c03aa4 --- /dev/null +++ b/src/include/lwip/prot/tcp.h @@ -0,0 +1,97 @@ +/** + * @file + * TCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_TCP_H +#define LWIP_HDR_PROT_TCP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* TCP header flags bits */ +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U +/* Valid TCP header flags */ +#define TCP_FLAGS 0x3fU + +#define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) +#define TCPH_FLAGS(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_TCP_H */ diff --git a/src/include/lwip/prot/udp.h b/src/include/lwip/prot/udp.h new file mode 100644 index 00000000..664f19a3 --- /dev/null +++ b/src/include/lwip/prot/udp.h @@ -0,0 +1,68 @@ +/** + * @file + * UDP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_UDP_H +#define LWIP_HDR_PROT_UDP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_UDP_H */ diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index f92c8ee9..30aa1471 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -104,6 +104,8 @@ void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *re u8_t raw_input (struct pbuf *p, struct netif *inp); #define raw_init() /* Compatibility define, no init needed. */ +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + /* for compatibility with older implementation */ #define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 20ba6293..9d76776f 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -48,6 +48,7 @@ #include "lwip/ip_addr.h" #include "lwip/err.h" #include "lwip/inet.h" +#include "lwip/errno.h" #ifdef __cplusplus extern "C" { @@ -427,6 +428,8 @@ typedef struct fd_set #elif LWIP_SOCKET_OFFSET #error LWIP_SOCKET_OFFSET does not work with external FD_SET! +#elif FD_SETSIZE < MEMP_NUM_NETCONN +#error "external FD_SETSIZE too small for number of sockets" #endif /* FD_SET */ /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided diff --git a/src/include/lwip/stats.h b/src/include/lwip/stats.h index 99f49cce..bcda2ace 100644 --- a/src/include/lwip/stats.h +++ b/src/include/lwip/stats.h @@ -189,16 +189,16 @@ struct stats_mib2_netif_ctrs { /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were * not addressed to a multicast or broadcast address at this sub-layer */ u32_t ifinucastpkts; - /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were * addressed to a multicast or broadcast address at this sub-layer */ u32_t ifinnucastpkts; - /** The number of inbound packets which were chosen to be discarded even though no errors had - * been detected to prevent their being deliverable to a higher-layer protocol. One possible + /** The number of inbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being deliverable to a higher-layer protocol. One possible * reason for discarding such a packet could be to free up buffer space */ u32_t ifindiscards; - /** For packet-oriented interfaces, the number of inbound packets that contained errors + /** For packet-oriented interfaces, the number of inbound packets that contained errors * preventing them from being deliverable to a higher-layer protocol. For character- - * oriented or fixed-length interfaces, the number of inbound transmission units that + * oriented or fixed-length interfaces, the number of inbound transmission units that * contained errors preventing them from being deliverable to a higher-layer protocol. */ u32_t ifinerrors; /** For packet-oriented interfaces, the number of packets received via the interface which @@ -408,7 +408,7 @@ void stats_init(void); #define MEMP_STATS_DISPLAY(i) #define MEMP_STATS_GET(x, i) 0 #endif - + #if SYS_STATS #define SYS_STATS_INC(x) STATS_INC(sys.x) #define SYS_STATS_DEC(x) STATS_DEC(sys.x) diff --git a/src/include/lwip/sys.h b/src/include/lwip/sys.h index c05af04e..bb06a404 100644 --- a/src/include/lwip/sys.h +++ b/src/include/lwip/sys.h @@ -60,10 +60,10 @@ * @defgroup sys_prot Critical sections * @ingroup sys_layer * Used to protect short regions of code against concurrent access. - * - Your system is a bare-metal system (probably with an RTOS) + * - Your system is a bare-metal system (probably with an RTOS) * and interrupts are under your control: * Implement this as LockInterrupts() / UnlockInterrupts() - * - Your system uses an RTOS with deferred interrupt handling from a + * - Your system uses an RTOS with deferred interrupt handling from a * worker thread: Implement as a global mutex or lock/unlock scheduler * - Your system uses a high-level OS with e.g. POSIX signals: * Implement as a global mutex @@ -160,9 +160,11 @@ typedef void (*lwip_thread_fn)(void *arg); /** * @ingroup sys_mutex - * Create a new mutex + * Create a new mutex. + * Note that mutexes are expected to not be taken recursively by the lwIP code, + * so both implementation types (recursive or non-recursive) should work. * @param mutex pointer to the mutex to create - * @return a new mutex + * @return ERR_OK if successful, another err_t otherwise */ err_t sys_mutex_new(sys_mutex_t *mutex); /** diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index 0ae49a0f..35584b45 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -350,11 +350,13 @@ struct tcp_pcb * tcp_new (void); struct tcp_pcb * tcp_new_ip_type (u8_t type); void tcp_arg (struct tcp_pcb *pcb, void *arg); -void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +#if LWIP_CALLBACK_API void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); -void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +#endif /* LWIP_CALLBACK_API */ +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); #define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) #define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h index 796f34aa..f2f6b469 100644 --- a/src/include/lwip/tcpip.h +++ b/src/include/lwip/tcpip.h @@ -52,7 +52,9 @@ extern "C" { #if LWIP_TCPIP_CORE_LOCKING /** The global semaphore to lock the stack. */ extern sys_mutex_t lock_tcpip_core; +/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ #define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ #define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) #else /* LWIP_TCPIP_CORE_LOCKING */ #define LOCK_TCPIP_CORE() @@ -76,7 +78,7 @@ err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); err_t tcpip_input(struct pbuf *p, struct netif *inp); err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); -/** +/** * @ingroup lwip_os * @see tcpip_callback_with_block */ @@ -90,10 +92,10 @@ err_t tcpip_trycallback(struct tcpip_callback_msg* msg); err_t pbuf_free_callback(struct pbuf *p); err_t mem_free_callback(void *m); -#if LWIP_TCPIP_TIMEOUT +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); err_t tcpip_untimeout(sys_timeout_handler h, void *arg); -#endif /* LWIP_TCPIP_TIMEOUT */ +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ #ifdef __cplusplus } diff --git a/src/include/lwip/timeouts.h b/src/include/lwip/timeouts.h index 4988b151..c9b93aa0 100644 --- a/src/include/lwip/timeouts.h +++ b/src/include/lwip/timeouts.h @@ -103,9 +103,9 @@ void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); #endif /* LWIP_DEBUG_TIMERNAMES */ void sys_untimeout(sys_timeout_handler handler, void *arg); +void sys_restart_timeouts(void); #if NO_SYS void sys_check_timeouts(void); -void sys_restart_timeouts(void); u32_t sys_timeouts_sleeptime(void); #else /* NO_SYS */ void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index a0381ddd..b9299073 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -47,29 +47,12 @@ #include "lwip/ip_addr.h" #include "lwip/ip.h" #include "lwip/ip6_addr.h" +#include "lwip/prot/udp.h" #ifdef __cplusplus extern "C" { #endif -#define UDP_HLEN 8 - -/* Fields are (of course) in network byte order. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct udp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ - PACK_STRUCT_FIELD(u16_t len); - PACK_STRUCT_FIELD(u16_t chksum); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - #define UDP_FLAGS_NOCHKSUM 0x01U #define UDP_FLAGS_UDPLITE 0x02U #define UDP_FLAGS_CONNECTED 0x04U @@ -188,9 +171,7 @@ void udp_debug_print(struct udp_hdr *udphdr); #define udp_debug_print(udphdr) #endif -#if LWIP_IPV4 -void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr); -#endif /* LWIP_IPV4 */ +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); #ifdef __cplusplus } diff --git a/src/include/netif/etharp.h b/src/include/netif/etharp.h index df63a70a..b536fd28 100644 --- a/src/include/netif/etharp.h +++ b/src/include/netif/etharp.h @@ -1,2 +1,3 @@ /* ARP has been moved to core/ipv4, provide this #include for compatibility only */ #include "lwip/etharp.h" +#include "netif/ethernet.h" diff --git a/src/include/netif/ethernet.h b/src/include/netif/ethernet.h index 03bfe7f8..49649cbf 100644 --- a/src/include/netif/ethernet.h +++ b/src/include/netif/ethernet.h @@ -45,111 +45,12 @@ #include "lwip/pbuf.h" #include "lwip/netif.h" +#include "lwip/prot/ethernet.h" #ifdef __cplusplus extern "C" { #endif -#ifndef ETH_HWADDR_LEN -#ifdef ETHARP_HWADDR_LEN -#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ -#else -#define ETH_HWADDR_LEN 6 -#endif -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct eth_addr { - PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** Ethernet header */ -struct eth_hdr { -#if ETH_PAD_SIZE - PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); -#endif - PACK_STRUCT_FLD_S(struct eth_addr dest); - PACK_STRUCT_FLD_S(struct eth_addr src); - PACK_STRUCT_FIELD(u16_t type); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) - -#if ETHARP_SUPPORT_VLAN - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** VLAN header inserted between ethernet header and payload - * if 'type' in ethernet header is ETHTYPE_VLAN. - * See IEEE802.Q */ -struct eth_vlan_hdr { - PACK_STRUCT_FIELD(u16_t prio_vid); - PACK_STRUCT_FIELD(u16_t tpid); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_VLAN_HDR 4 -#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) - -#endif /* ETHARP_SUPPORT_VLAN */ - -/* A list of often ethtypes (although lwIP does not use all of them): */ -#define ETHTYPE_IP 0x0800U /* Internet protocol v4 */ -#define ETHTYPE_ARP 0x0806U /* Address resolution protocol */ -#define ETHTYPE_WOL 0x0842U /* Wake on lan */ -#define ETHTYPE_VLAN 0x8100U /* Virtual local area network */ -#define ETHTYPE_IPV6 0x86DDU /* Internet protocol v6 */ -#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ -#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ -#define ETHTYPE_JUMBO 0x8870U /* Jumbo Frames */ -#define ETHTYPE_PROFINET 0x8892U /* Process field network */ -#define ETHTYPE_ETHERCAT 0x88A4U /* Ethernet for control automation technology */ -#define ETHTYPE_LLDP 0x88CCU /* Link layer discovery protocol */ -#define ETHTYPE_SERCOS 0x88CDU /* Serial real-time communication system */ -#define ETHTYPE_PTP 0x88F7U /* Precision time protocol */ -#define ETHTYPE_QINQ 0x9100U /* Q-in-Q, 802.1ad */ - -/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ -#define LL_IP4_MULTICAST_ADDR_0 0x01 -#define LL_IP4_MULTICAST_ADDR_1 0x00 -#define LL_IP4_MULTICAST_ADDR_2 0x5e - -/** IPv6 multicast uses this prefix */ -#define LL_IP6_MULTICAST_ADDR_0 0x33 -#define LL_IP6_MULTICAST_ADDR_1 0x33 - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables - * or known to be 32-bit aligned within the protocol header. */ -#ifndef ETHADDR32_COPY -#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local - * variables and known to be 16-bit aligned within the protocol header. */ -#ifndef ETHADDR16_COPY -#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - #if LWIP_ARP || LWIP_ETHERNET /** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) @@ -163,8 +64,7 @@ PACK_STRUCT_END #endif err_t ethernet_input(struct pbuf *p, struct netif *netif); - -#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) +err_t ethernet_output(struct netif* netif, struct pbuf* p, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); extern const struct eth_addr ethbroadcast, ethzero; diff --git a/src/include/netif/ppp/eui64.h b/src/include/netif/ppp/eui64.h index 1b5147f4..20ac22ee 100644 --- a/src/include/netif/ppp/eui64.h +++ b/src/include/netif/ppp/eui64.h @@ -84,7 +84,7 @@ typedef union #define eui64_set32(e, l) do { \ (e).e32[0] = 0; \ - (e).e32[1] = htonl(l); \ + (e).e32[1] = lwip_htonl(l); \ } while (0) #define eui64_setlo32(e, l) eui64_set32(e, l) diff --git a/src/include/netif/ppp/mppe.h b/src/include/netif/ppp/mppe.h index 551a47e5..1ae8a5d9 100644 --- a/src/include/netif/ppp/mppe.h +++ b/src/include/netif/ppp/mppe.h @@ -59,7 +59,7 @@ * This is not nice ... the alternative is a bitfield struct though. * And unfortunately, we cannot share the same bits for the option * names above since C and H are the same bit. We could do a u_int32 - * but then we have to do a htonl() all the time and/or we still need + * but then we have to do a lwip_htonl() all the time and/or we still need * to know which octet is which. */ #define MPPE_C_BIT 0x01 /* MPPC */ diff --git a/src/include/netif/ppp/ppp.h b/src/include/netif/ppp/ppp.h index 016d6ba2..d9ea097e 100644 --- a/src/include/netif/ppp/ppp.h +++ b/src/include/netif/ppp/ppp.h @@ -110,18 +110,18 @@ * Values for phase. */ #define PPP_PHASE_DEAD 0 -#define PPP_PHASE_INITIALIZE 1 -#define PPP_PHASE_SERIALCONN 2 -#define PPP_PHASE_DORMANT 3 -#define PPP_PHASE_ESTABLISH 4 -#define PPP_PHASE_AUTHENTICATE 5 -#define PPP_PHASE_CALLBACK 6 -#define PPP_PHASE_NETWORK 7 -#define PPP_PHASE_RUNNING 8 -#define PPP_PHASE_TERMINATE 9 -#define PPP_PHASE_DISCONNECT 10 -#define PPP_PHASE_HOLDOFF 11 -#define PPP_PHASE_MASTER 12 +#define PPP_PHASE_MASTER 1 +#define PPP_PHASE_HOLDOFF 2 +#define PPP_PHASE_INITIALIZE 3 +#define PPP_PHASE_SERIALCONN 4 +#define PPP_PHASE_DORMANT 5 +#define PPP_PHASE_ESTABLISH 6 +#define PPP_PHASE_AUTHENTICATE 7 +#define PPP_PHASE_CALLBACK 8 +#define PPP_PHASE_NETWORK 9 +#define PPP_PHASE_RUNNING 10 +#define PPP_PHASE_TERMINATE 11 +#define PPP_PHASE_DISCONNECT 12 /* Error codes. */ #define PPPERR_NONE 0 /* No error. */ @@ -324,6 +324,7 @@ struct ppp_pcb_s { /* flags */ #if PPP_IPV4_SUPPORT + unsigned int ask_for_local :1; /* request our address from peer */ unsigned int ipcp_is_open :1; /* haven't called np_finished() */ unsigned int ipcp_is_up :1; /* have called ipcp_up() */ unsigned int if4_up :1; /* True when the IPv4 interface is up. */ @@ -475,7 +476,8 @@ void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *pas * * Default is unset (0.0.0.0). */ -#define ppp_set_ipcp_ouraddr(ppp, addr) (ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr)) +#define ppp_set_ipcp_ouraddr(ppp, addr) do { ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr); \ + ppp->ask_for_local = ppp->ipcp_wantoptions.ouraddr != 0; } while(0) #define ppp_set_ipcp_hisaddr(ppp, addr) (ppp->ipcp_wantoptions.hisaddr = ip4_addr_get_u32(addr)) #if LWIP_DNS /* diff --git a/src/include/netif/ppp/ppp_impl.h b/src/include/netif/ppp/ppp_impl.h index 1b27415f..e9338de5 100644 --- a/src/include/netif/ppp/ppp_impl.h +++ b/src/include/netif/ppp/ppp_impl.h @@ -394,9 +394,6 @@ int ppp_init(void); ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -/* Called when link is starting */ -void ppp_link_start(ppp_pcb *pcb); - /* Initiate LCP open request */ void ppp_start(ppp_pcb *pcb); @@ -623,7 +620,7 @@ 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) */ #if PRINTPKT_SUPPORT -void ppp_dump_packet(const char *tag, unsigned char *p, int len); +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); /* dump packet to debug log if interesting */ #endif /* PRINTPKT_SUPPORT */ diff --git a/src/include/netif/ppp/ppp_opts.h b/src/include/netif/ppp/ppp_opts.h index 75541f44..fa79c090 100644 --- a/src/include/netif/ppp/ppp_opts.h +++ b/src/include/netif/ppp/ppp_opts.h @@ -296,8 +296,8 @@ #ifndef VJ_SUPPORT #define VJ_SUPPORT 1 #endif -/* VJ compression is only supported for IPv4 over PPPoS. */ -#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT +/* VJ compression is only supported for TCP over IPv4 over PPPoS. */ +#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP #undef VJ_SUPPORT #define VJ_SUPPORT 0 #endif /* !PPPOS_SUPPORT */ diff --git a/src/include/netif/ppp/pppol2tp.h b/src/include/netif/ppp/pppol2tp.h index 93842556..f03950e6 100644 --- a/src/include/netif/ppp/pppol2tp.h +++ b/src/include/netif/ppp/pppol2tp.h @@ -34,8 +34,8 @@ #include "netif/ppp/ppp_opts.h" #if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ -#ifndef PPPOL2TP_H_ -#define PPPOL2TP_H_ +#ifndef PPPOL2TP_H +#define PPPOL2TP_H #include "ppp.h" @@ -197,5 +197,5 @@ ppp_pcb *pppol2tp_create(struct netif *pppif, const u8_t *secret, u8_t secret_len, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOL2TP_H_ */ +#endif /* PPPOL2TP_H */ #endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/src/include/posix/errno.h b/src/include/posix/errno.h new file mode 100644 index 00000000..5917c75e --- /dev/null +++ b/src/include/posix/errno.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/errno.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/errno.h" diff --git a/src/netif/FILES b/src/netif/FILES index 501edac3..a3ff431d 100644 --- a/src/netif/FILES +++ b/src/netif/FILES @@ -2,30 +2,23 @@ This directory contains generic network interface device drivers that do not contain any hardware or architecture specific code. The files are: -etharp.c - Implements the ARP (Address Resolution Protocol) over - Ethernet. The code in this file should be used together with - Ethernet device drivers. Note that this module has been - largely made Ethernet independent so you should be able to - adapt this for other link layers (such as Firewire). +ethernet.c + Shared code for Ethernet based interfaces. ethernetif.c An example of how an Ethernet device driver could look. This file can be used as a "skeleton" for developing new Ethernet network device drivers. It uses the etharp.c ARP code. -loopif.c - A "loopback" network interface driver. It requires configuration - through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). +lowpan6.c + A 6LoWPAN implementation as a netif. slipif.c A generic implementation of the SLIP (Serial Line IP) protocol. It requires a sio (serial I/O) module to work. -lowpan6.c - 6LoWPAN implementation - ppp/ Point-to-Point Protocol stack The lwIP PPP support is based from pppd (http://ppp.samba.org) with huge changes to match code size and memory requirements for embedded - devices. Please read ppp/PPPD_FOLLOWUP for a detailed explanation. + devices. Please read /doc/ppp.txt and ppp/PPPD_FOLLOWUP for a detailed + explanation. diff --git a/src/netif/ethernet.c b/src/netif/ethernet.c index 26e360af..9b76e85f 100644 --- a/src/netif/ethernet.c +++ b/src/netif/ethernet.c @@ -1,6 +1,9 @@ /** * @file * Ethernet common functions + * + * @defgroup ethernet Ethernet + * @ingroup callbackstyle_api */ /* @@ -65,6 +68,10 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}}; * * @param p the received packet, p->payload pointing to the ethernet header * @param netif the network interface on which the packet was received + * + * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + * @see ETHARP_SUPPORT_VLAN + * @see LWIP_HOOK_VLAN_CHECK */ err_t ethernet_input(struct pbuf *p, struct netif *netif) @@ -91,7 +98,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], - htons(ethhdr->type))); + lwip_htons(ethhdr->type))); type = ethhdr->type; #if ETHARP_SUPPORT_VLAN @@ -123,7 +130,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) #endif /* ETHARP_SUPPORT_VLAN */ #if LWIP_ARP_FILTER_NETIF - netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); #endif /* LWIP_ARP_FILTER_NETIF*/ if (ethhdr->dest.addr[0] & 1) { @@ -139,7 +146,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) } #if LWIP_IPV6 else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && - (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { + (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { /* mark the pbuf as link-layer multicast */ p->flags |= PBUF_FLAG_LLMCAST; } @@ -157,10 +164,6 @@ ethernet_input(struct pbuf *p, struct netif *netif) if (!(netif->flags & NETIF_FLAG_ETHARP)) { goto free_and_return; } -#if ETHARP_TRUST_IP_MAC - /* update ARP table */ - etharp_ip_input(netif, p); -#endif /* ETHARP_TRUST_IP_MAC */ /* skip Ethernet header */ if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, @@ -178,8 +181,19 @@ ethernet_input(struct pbuf *p, struct netif *netif) if (!(netif->flags & NETIF_FLAG_ETHARP)) { goto free_and_return; } - /* pass p to ARP module */ - etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } else { + /* pass p to ARP module */ + etharp_input(p, netif); + } break; #endif /* LWIP_IPV4 && LWIP_ARP */ #if PPPOE_SUPPORT @@ -208,6 +222,11 @@ ethernet_input(struct pbuf *p, struct netif *netif) #endif /* LWIP_IPV6 */ default: +#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { + break; + } +#endif ETHARP_STATS_INC(etharp.proterr); ETHARP_STATS_INC(etharp.drop); MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); @@ -222,4 +241,70 @@ free_and_return: pbuf_free(p); return ERR_OK; } + +/** + * @ingroup ethernet + * Send an ethernet packet on the network using netif->linkoutput(). + * The ethernet header is filled in before sending. + * + * @see LWIP_HOOK_VLAN_SET + * + * @param netif the lwIP network interface on which to send the packet + * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. + * @param src the source MAC address to be copied into the ethernet header + * @param dst the destination MAC address to be copied into the ethernet header + * @param eth_type ethernet type (@ref eth_type) + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +err_t +ethernet_output(struct netif* netif, struct pbuf* p, + const struct eth_addr* src, const struct eth_addr* dst, + u16_t eth_type) +{ + 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 (vlan_prio_vid >= 0) { + struct eth_vlan_hdr* vlanhdr; + + LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); + + if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { + goto pbuf_header_failed; + } + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); + vlanhdr->tpid = eth_type_be; + vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); + + eth_type_be = PP_HTONS(ETHTYPE_VLAN); + } else +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + { + if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { + goto pbuf_header_failed; + } + } + + ethhdr = (struct eth_hdr*)p->payload; + ethhdr->type = eth_type_be; + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + + LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_output: sending packet %p\n", (void *)p)); + + /* send the packet */ + return netif->linkoutput(netif, p); + +pbuf_header_failed: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("ethernet_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; +} + #endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/src/netif/ethernetif.c b/src/netif/ethernetif.c index 973b3e15..dc8ae6c4 100644 --- a/src/netif/ethernetif.c +++ b/src/netif/ethernetif.c @@ -110,7 +110,7 @@ low_level_init(struct netif *netif) if (netif->mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - netif->mld_mac_filter(netif, &ip6_allnodes_ll, MLD6_ADD_MAC_FILTER); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ @@ -266,7 +266,7 @@ ethernetif_input(struct netif *netif) /* if no packet could be read, silently ignore this */ if (p != NULL) { /* pass all packets to ethernet_input, which decides what packets it supports */ - if (netif->input(p, netif) != ERR_OK) { + if (netif->input(p, netif) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); p = NULL; diff --git a/src/netif/lowpan6.c b/src/netif/lowpan6.c index 407848c4..eca9a453 100644 --- a/src/netif/lowpan6.c +++ b/src/netif/lowpan6.c @@ -160,13 +160,13 @@ lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_add if (mac_addr->addr_len == 2) { if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { - if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { + if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { return 3; } } } else if (mac_addr->addr_len == 8) { - if ((ip6addr->addr[2] == ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && - (ip6addr->addr[3] == ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { + if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && + (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { return 3; } } @@ -611,7 +611,7 @@ lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) * @param q The pbuf(s) containing the IP packet to be sent. * @param ip6addr The IP address of the packet destination. * - * @return + * @return err_t */ err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) @@ -768,7 +768,7 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); ip6hdr->src.addr[1] = 0; ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); lowpan6_offset += 2; } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { @@ -776,11 +776,11 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 ip6hdr->src.addr[1] = 0; if (src->addr_len == 2) { ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); } else { - ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); } } @@ -815,15 +815,15 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 lowpan6_offset += 8; } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); lowpan6_offset += 2; } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { if (src->addr_len == 2) { ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); } else { - ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); } } } @@ -843,22 +843,22 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); lowpan6_offset += 16; } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { - ip6hdr->dest.addr[0] = htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = htonl(lowpan6_buffer[lowpan6_offset++]); - ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); + ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); lowpan6_offset += 4; } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { - ip6hdr->dest.addr[0] = htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); ip6hdr->dest.addr[1] = 0; ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); lowpan6_offset += 3; } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); ip6hdr->dest.addr[1] = 0; ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = htonl(lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); } } else { @@ -894,15 +894,15 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 lowpan6_offset += 8; } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); lowpan6_offset += 2; } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { if (dest->addr_len == 2) { ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); } else { - ip6hdr->dest.addr[2] = htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); - ip6hdr->dest.addr[3] = htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); + ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); + ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); } } } @@ -927,26 +927,26 @@ lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_8 /* Decompress ports */ i = lowpan6_buffer[lowpan6_offset++] & 0x03; if (i == 0) { - udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); lowpan6_offset += 4; } else if (i == 0x01) { - udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); lowpan6_offset += 3; } else if (i == 0x02) { - udphdr->src = htons(0xf000 | lowpan6_buffer[lowpan6_offset]); - udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); + udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); lowpan6_offset += 3; } else if (i == 0x03) { - udphdr->src = htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); - udphdr->dest = htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); + udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); + udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); lowpan6_offset += 1; } - udphdr->chksum = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); lowpan6_offset += 2; - udphdr->len = htons(p->tot_len - lowpan6_offset + UDP_HLEN); + udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN); ip6_offset += UDP_HLEN; } else { diff --git a/src/netif/ppp/auth.c b/src/netif/ppp/auth.c index 6e80352c..c8673ad0 100644 --- a/src/netif/ppp/auth.c +++ b/src/netif/ppp/auth.c @@ -618,7 +618,11 @@ void start_link(unit) * physical layer down. */ void link_terminated(ppp_pcb *pcb) { - if (pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_MASTER) + if (pcb->phase == PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + || pcb->phase == PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) return; new_phase(pcb, PPP_PHASE_DISCONNECT); @@ -639,7 +643,6 @@ void link_terminated(ppp_pcb *pcb) { lcp_lowerdown(pcb); - new_phase(pcb, PPP_PHASE_DEAD); ppp_link_terminated(pcb); #if 0 /* @@ -699,7 +702,11 @@ void link_down(ppp_pcb *pcb) { if (!doing_multilink) { upper_layers_down(pcb); - if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) new_phase(pcb, PPP_PHASE_ESTABLISH); } /* XXX if doing_multilink, should do something to stop @@ -2114,10 +2121,10 @@ set_allowed_addrs(unit, addrs, opts) } else { np = getnetbyname (ptr_word); if (np != NULL && np->n_addrtype == AF_INET) { - a = htonl ((u32_t)np->n_net); + a = lwip_htonl ((u32_t)np->n_net); if (ptr_mask == NULL) { /* calculate appropriate mask for net */ - ah = ntohl(a); + ah = lwip_ntohl(a); if (IN_CLASSA(ah)) mask = IN_CLASSA_NET; else if (IN_CLASSB(ah)) @@ -2143,10 +2150,10 @@ set_allowed_addrs(unit, addrs, opts) ifunit, ptr_word); continue; } - a = htonl((ntohl(a) & mask) + offset); + a = lwip_htonl((lwip_ntohl(a) & mask) + offset); mask = ~(u32_t)0; } - ip[n].mask = htonl(mask); + ip[n].mask = lwip_htonl(mask); ip[n].base = a & ip[n].mask; ++n; if (~mask == 0 && suggested_ip == 0) @@ -2227,7 +2234,7 @@ int bad_ip_adrs(addr) u32_t addr; { - addr = ntohl(addr); + addr = lwip_ntohl(addr); return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || IN_MULTICAST(addr) || IN_BADCLASS(addr); } diff --git a/src/netif/ppp/ipcp.c b/src/netif/ppp/ipcp.c index 2cdcba85..b7c766eb 100644 --- a/src/netif/ppp/ipcp.c +++ b/src/netif/ppp/ipcp.c @@ -350,11 +350,8 @@ setvjslots(argv) { int value; -/* FIXME: found what int_option() did */ -#if PPP_OPTIONS if (!int_option(*argv, &value)) return 0; -#endif /* PPP_OPTIONS */ if (value < 2 || value > 16) { option_error("vj-max-slots value must be between 2 and 16"); @@ -542,7 +539,7 @@ setnetmask(argv) p = *argv; n = parse_dotted_ip(p, &mask); - mask = htonl(mask); + mask = lwip_htonl(mask); if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { option_error("invalid netmask value '%s'", *argv); @@ -728,13 +725,8 @@ static void ipcp_resetci(fsm *f) { wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ #endif /* LWIP_DNS */ *go = *wo; -#if 0 /* UNUSED */ - /* We don't need ask_for_local, this is only useful for setup which - * can determine the local IP address from the system hostname. - */ - if (!ask_for_local) + if (!pcb->ask_for_local) go->ouraddr = 0; -#endif /* UNUSED */ #if 0 /* UNUSED */ if (ip_choose_hook) { ip_choose_hook(&wo->hisaddr); @@ -822,9 +814,9 @@ static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { u32_t l; \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_ADDRS, ucp); \ - l = ntohl(val1); \ + l = lwip_ntohl(val1); \ PUTLONG(l, ucp); \ - l = ntohl(val2); \ + l = lwip_ntohl(val2); \ PUTLONG(l, ucp); \ len -= CILEN_ADDRS; \ } else \ @@ -855,7 +847,7 @@ static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { u32_t l; \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_ADDR, ucp); \ - l = ntohl(val); \ + l = lwip_ntohl(val); \ PUTLONG(l, ucp); \ len -= CILEN_ADDR; \ } else \ @@ -869,7 +861,7 @@ static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { u32_t l; \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_ADDR, ucp); \ - l = ntohl(addr); \ + l = lwip_ntohl(addr); \ PUTLONG(l, ucp); \ len -= CILEN_ADDR; \ } else \ @@ -884,7 +876,7 @@ static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { u32_t l; \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_ADDR, ucp); \ - l = ntohl(addr); \ + l = lwip_ntohl(addr); \ PUTLONG(l, ucp); \ len -= CILEN_ADDR; \ } else \ @@ -953,11 +945,11 @@ static int ipcp_ackci(fsm *f, u_char *p, int len) { citype != opt) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ if (val1 != cilong) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ if (val2 != cilong) \ goto bad; \ } @@ -998,7 +990,7 @@ static int ipcp_ackci(fsm *f, u_char *p, int len) { citype != opt) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ if (val != cilong) \ goto bad; \ } @@ -1014,7 +1006,7 @@ static int ipcp_ackci(fsm *f, u_char *p, int len) { if (cilen != CILEN_ADDR || citype != opt) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ if (addr != cilong) \ goto bad; \ } @@ -1031,7 +1023,7 @@ static int ipcp_ackci(fsm *f, u_char *p, int len) { if (cilen != CILEN_ADDR || citype != opt) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ if (addr != cilong) \ goto bad; \ } @@ -1112,9 +1104,9 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - ciaddr1 = htonl(l); \ + ciaddr1 = lwip_htonl(l); \ GETLONG(l, p); \ - ciaddr2 = htonl(l); \ + ciaddr2 = lwip_htonl(l); \ no.old_addrs = 1; \ code \ } @@ -1141,7 +1133,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - ciaddr1 = htonl(l); \ + ciaddr1 = lwip_htonl(l); \ no.neg = 1; \ code \ } @@ -1155,7 +1147,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - cidnsaddr = htonl(l); \ + cidnsaddr = lwip_htonl(l); \ no.neg = 1; \ code \ } @@ -1271,11 +1263,11 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { goto bad; try_.neg_addr = 0; GETLONG(l, p); - ciaddr1 = htonl(l); + ciaddr1 = lwip_htonl(l); if (ciaddr1 && go->accept_local) try_.ouraddr = ciaddr1; GETLONG(l, p); - ciaddr2 = htonl(l); + ciaddr2 = lwip_htonl(l); if (ciaddr2 && go->accept_remote) try_.hisaddr = ciaddr2; no.old_addrs = 1; @@ -1285,7 +1277,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { goto bad; try_.old_addrs = 0; GETLONG(l, p); - ciaddr1 = htonl(l); + ciaddr1 = lwip_htonl(l); if (ciaddr1 && go->accept_local) try_.ouraddr = ciaddr1; if (try_.ouraddr != 0) @@ -1297,7 +1289,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) goto bad; GETLONG(l, p); - try_.dnsaddr[0] = htonl(l); + try_.dnsaddr[0] = lwip_htonl(l); try_.req_dns1 = 1; no.req_dns1 = 1; break; @@ -1305,7 +1297,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) goto bad; GETLONG(l, p); - try_.dnsaddr[1] = htonl(l); + try_.dnsaddr[1] = lwip_htonl(l); try_.req_dns2 = 1; no.req_dns2 = 1; break; @@ -1316,7 +1308,7 @@ static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { if (cilen != CILEN_ADDR) goto bad; GETLONG(l, p); - ciaddr1 = htonl(l); + ciaddr1 = lwip_htonl(l); if (ciaddr1) try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; break; @@ -1372,12 +1364,12 @@ static int ipcp_rejci(fsm *f, u_char *p, int len) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ /* Check rejected value. */ \ if (cilong != val1) \ goto bad; \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ /* Check rejected value. */ \ if (cilong != val2) \ goto bad; \ @@ -1417,7 +1409,7 @@ static int ipcp_rejci(fsm *f, u_char *p, int len) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ /* Check rejected value. */ \ if (cilong != val) \ goto bad; \ @@ -1434,7 +1426,7 @@ static int ipcp_rejci(fsm *f, u_char *p, int len) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ /* Check rejected value. */ \ if (cilong != dnsaddr) \ goto bad; \ @@ -1452,7 +1444,7 @@ static int ipcp_rejci(fsm *f, u_char *p, int len) { len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ - cilong = htonl(l); \ + cilong = lwip_htonl(l); \ /* Check rejected value. */ \ if (cilong != addr) \ goto bad; \ @@ -1575,13 +1567,13 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { * then accept it. */ GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); + ciaddr1 = lwip_htonl(tl); if (ciaddr1 != wo->hisaddr && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; if (!reject_if_disagree) { DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->hisaddr); + tl = lwip_ntohl(wo->hisaddr); PUTLONG(tl, p); } } else if (ciaddr1 == 0 && wo->hisaddr == 0) { @@ -1598,13 +1590,13 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { * but disagree about it, then NAK it with our idea. */ GETLONG(tl, p); /* Parse desination address (ours) */ - ciaddr2 = htonl(tl); + ciaddr2 = lwip_htonl(tl); if (ciaddr2 != wo->ouraddr) { if (ciaddr2 == 0 || !wo->accept_local) { orc = CONFNAK; if (!reject_if_disagree) { DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->ouraddr); + tl = lwip_ntohl(wo->ouraddr); PUTLONG(tl, p); } } else { @@ -1631,13 +1623,13 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { * then accept it. */ GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); + ciaddr1 = lwip_htonl(tl); if (ciaddr1 != wo->hisaddr && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; if (!reject_if_disagree) { DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->hisaddr); + tl = lwip_ntohl(wo->hisaddr); PUTLONG(tl, p); } } else if (ciaddr1 == 0 && wo->hisaddr == 0) { @@ -1666,9 +1658,9 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { break; } GETLONG(tl, p); - if (htonl(tl) != ao->dnsaddr[d]) { + if (lwip_htonl(tl) != ao->dnsaddr[d]) { DECPTR(sizeof(u32_t), p); - tl = ntohl(ao->dnsaddr[d]); + tl = lwip_ntohl(ao->dnsaddr[d]); PUTLONG(tl, p); orc = CONFNAK; } @@ -1688,9 +1680,9 @@ static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { break; } GETLONG(tl, p); - if (htonl(tl) != ao->winsaddr[d]) { + if (lwip_htonl(tl) != ao->winsaddr[d]) { DECPTR(sizeof(u32_t), p); - tl = ntohl(ao->winsaddr[d]); + tl = lwip_ntohl(ao->winsaddr[d]); PUTLONG(tl, p); orc = CONFNAK; } @@ -1793,7 +1785,7 @@ endswitch: } PUTCHAR(CI_ADDR, ucp); PUTCHAR(CILEN_ADDR, ucp); - tl = ntohl(wo->hisaddr); + tl = lwip_ntohl(wo->hisaddr); PUTLONG(tl, ucp); } @@ -1850,12 +1842,12 @@ ip_demand_conf(u) if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { /* make up an arbitrary address for the peer */ - wo->hisaddr = htonl(0x0a707070 + ifunit); + wo->hisaddr = lwip_htonl(0x0a707070 + ifunit); wo->accept_remote = 1; } if (wo->ouraddr == 0) { /* make up an arbitrary address for us */ - wo->ouraddr = htonl(0x0a404040 + ifunit); + wo->ouraddr = lwip_htonl(0x0a404040 + ifunit); wo->accept_local = 1; ask_for_local = 0; /* don't tell the peer this address */ } @@ -1917,7 +1909,7 @@ static void ipcp_up(fsm *f) { return; } if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { - ho->hisaddr = htonl(0x0a404040); + ho->hisaddr = lwip_htonl(0x0a404040); ppp_warn("Could not determine remote IP address: defaulting to %I", ho->hisaddr); } @@ -1947,11 +1939,29 @@ static void ipcp_up(fsm *f) { } #endif /* LWIP_DNS */ -/* FIXME: check why it fails, just to know */ -#if 0 /* Unused */ /* * Check that the peer is allowed to use the IP address it wants. */ + if (ho->hisaddr != 0) { + u32_t addr = lwip_ntohl(ho->hisaddr); + if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET + || IP_MULTICAST(addr) || IP_BADCLASS(addr) + /* + * For now, consider that PPP in server mode with peer required + * to authenticate must provide the peer IP address, reject any + * IP address wanted by peer different than the one we wanted. + */ +#if PPP_SERVER && PPP_AUTH_SUPPORT + || (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); + ipcp_close(pcb, "Unauthorized remote IP address"); + return; + } + } +#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); ipcp_close(f->unit, "Unauthorized remote IP address"); @@ -2271,9 +2281,9 @@ static int ipcp_printpkt(const u_char *p, int plen, if (olen == CILEN_ADDRS) { p += 2; GETLONG(cilong, p); - printer(arg, "addrs %I", htonl(cilong)); + printer(arg, "addrs %I", lwip_htonl(cilong)); GETLONG(cilong, p); - printer(arg, " %I", htonl(cilong)); + printer(arg, " %I", lwip_htonl(cilong)); } break; #if VJ_SUPPORT @@ -2299,7 +2309,7 @@ static int ipcp_printpkt(const u_char *p, int plen, if (olen == CILEN_ADDR) { p += 2; GETLONG(cilong, p); - printer(arg, "addr %I", htonl(cilong)); + printer(arg, "addr %I", lwip_htonl(cilong)); } break; #if LWIP_DNS @@ -2316,7 +2326,7 @@ static int ipcp_printpkt(const u_char *p, int plen, case CI_MS_WINS2: p += 2; GETLONG(cilong, p); - printer(arg, "ms-wins %I", htonl(cilong)); + printer(arg, "ms-wins %I", lwip_htonl(cilong)); break; #endif /* UNUSED - WINS */ default: diff --git a/src/netif/ppp/ipv6cp.c b/src/netif/ppp/ipv6cp.c index f0f4eee0..11c18df7 100644 --- a/src/netif/ppp/ipv6cp.c +++ b/src/netif/ppp/ipv6cp.c @@ -1093,7 +1093,7 @@ static void ipv6_check_options() { if (!wo->opt_local) { /* init interface identifier */ if (wo->use_ip && eui64_iszero(wo->ourid)) { - eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); + eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr)); if (!eui64_iszero(wo->ourid)) wo->opt_local = 1; } @@ -1104,7 +1104,7 @@ static void ipv6_check_options() { if (!wo->opt_remote) { if (wo->use_ip && eui64_iszero(wo->hisid)) { - eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr)); + eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr)); if (!eui64_iszero(wo->hisid)) wo->opt_remote = 1; } diff --git a/src/netif/ppp/lcp.c b/src/netif/ppp/lcp.c index b17964b2..90ed183b 100644 --- a/src/netif/ppp/lcp.c +++ b/src/netif/ppp/lcp.c @@ -423,7 +423,11 @@ void lcp_close(ppp_pcb *pcb, const char *reason) { fsm *f = &pcb->lcp_fsm; int oldstate; - if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) new_phase(pcb, PPP_PHASE_TERMINATE); if (f->flags & DELAYED_UP) { diff --git a/src/netif/ppp/multilink.c b/src/netif/ppp/multilink.c index 0d617a0f..62014e8c 100644 --- a/src/netif/ppp/multilink.c +++ b/src/netif/ppp/multilink.c @@ -469,7 +469,7 @@ get_default_epdisc(ep) if (hp != NULL) { addr = *(u32_t *)hp->h_addr; if (!bad_ip_adrs(addr)) { - addr = ntohl(addr); + addr = lwip_ntohl(addr); if (!LOCAL_IP_ADDR(addr)) { ep->class = EPD_IP; set_ip_epdisc(ep, addr); @@ -504,7 +504,7 @@ epdisc_to_str(ep) u32_t addr; GETLONG(addr, p); - slprintf(str, sizeof(str), "IP:%I", htonl(addr)); + slprintf(str, sizeof(str), "IP:%I", lwip_htonl(addr)); return str; } diff --git a/src/netif/ppp/ppp.c b/src/netif/ppp/ppp.c index d5e317cb..0e37eeb2 100644 --- a/src/netif/ppp/ppp.c +++ b/src/netif/ppp/ppp.c @@ -94,7 +94,6 @@ #include "lwip/tcpip.h" #include "lwip/api.h" #include "lwip/snmp.h" -#include "lwip/sys.h" #include "lwip/ip4.h" /* for ip4_input() */ #if PPP_IPV6_SUPPORT #include "lwip/ip6.h" /* for ip6_input() */ @@ -276,6 +275,7 @@ err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); if (holdoff == 0) { + new_phase(pcb, PPP_PHASE_INITIALIZE); return pcb->link_cb->connect(pcb, pcb->link_ctx_cb); } @@ -301,6 +301,7 @@ err_t ppp_listen(ppp_pcb *pcb) { PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); if (pcb->link_cb->listen) { + new_phase(pcb, PPP_PHASE_INITIALIZE); return pcb->link_cb->listen(pcb, pcb->link_ctx_cb); } return ERR_IF; @@ -335,6 +336,18 @@ ppp_close(ppp_pcb *pcb, u8_t nocarrier) return ERR_OK; } + /* Already terminating, nothing to do */ + if (pcb->phase >= PPP_PHASE_TERMINATE) { + return ERR_INPROGRESS; + } + + /* LCP not open, close link protocol */ + if (pcb->phase < PPP_PHASE_ESTABLISH) { + new_phase(pcb, PPP_PHASE_DISCONNECT); + ppp_link_terminated(pcb); + return ERR_OK; + } + /* * Only accept carrier lost signal on the stable running phase in order * to prevent changing the PPP phase FSM in transition phases. @@ -345,14 +358,14 @@ ppp_close(ppp_pcb *pcb, u8_t nocarrier) if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); lcp_lowerdown(pcb); - /* forced link termination, this will leave us at PPP_PHASE_DEAD. */ + /* forced link termination, this will force link protocol to disconnect. */ link_terminated(pcb); return ERR_OK; } /* Disconnect */ PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); - /* LCP close request, this will leave us at PPP_PHASE_DEAD. */ + /* LCP soft close request. */ lcp_close(pcb, "User request"); return ERR_OK; } @@ -432,6 +445,7 @@ static void ppp_do_connect(void *arg) { LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + new_phase(pcb, PPP_PHASE_INITIALIZE); pcb->link_cb->connect(pcb, pcb->link_ctx_cb); } @@ -508,7 +522,7 @@ static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protoc } #endif /* MPPE_SUPPORT */ -#if VJ_SUPPORT && LWIP_TCP +#if VJ_SUPPORT /* * Attempt Van Jacobson header compression if VJ is configured and * this is an IP packet. @@ -539,7 +553,7 @@ static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protoc return ERR_VAL; } } -#endif /* VJ_SUPPORT && LWIP_TCP */ +#endif /* VJ_SUPPORT */ #if CCP_SUPPORT switch (pcb->ccp_transmit_method) { @@ -681,7 +695,7 @@ ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, vo MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); if (!netif_add(pcb->netif, #if LWIP_IPV4 - IP4_ADDR_ANY, IP4_ADDR_BROADCAST, IP4_ADDR_ANY, + IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, #endif /* LWIP_IPV4 */ (void *)pcb, ppp_netif_init_cb, NULL)) { LWIP_MEMPOOL_FREE(PPP_PCB, pcb); @@ -705,13 +719,6 @@ ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, vo return pcb; } -/** Called when link is starting */ -void ppp_link_start(ppp_pcb *pcb) { - LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); - PPPDEBUG(LOG_DEBUG, ("ppp_link_start[%d]\n", pcb->netif->num)); - new_phase(pcb, PPP_PHASE_INITIALIZE); -} - /** Initiate LCP open request */ void ppp_start(ppp_pcb *pcb) { PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); @@ -725,11 +732,12 @@ void ppp_start(ppp_pcb *pcb) { memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); #endif /* MPPE_SUPPORT */ -#if VJ_SUPPORT && LWIP_TCP +#if VJ_SUPPORT vj_compress_init(&pcb->vj_comp); -#endif /* VJ_SUPPORT && LWIP_TCP */ +#endif /* VJ_SUPPORT */ /* Start protocol */ + new_phase(pcb, PPP_PHASE_ESTABLISH); lcp_open(pcb); lcp_lowerup(pcb); PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); @@ -746,6 +754,7 @@ void ppp_link_failed(ppp_pcb *pcb) { /** Called when link is normally down (i.e. it was asked to end) */ void ppp_link_end(ppp_pcb *pcb) { PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); if (pcb->err_code == PPPERR_NONE) { pcb->err_code = PPPERR_CONNECT; } @@ -771,7 +780,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; #if PRINTPKT_SUPPORT - ppp_dump_packet("rcvd", (unsigned char *)pb->payload, pb->len); + ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); #endif /* PRINTPKT_SUPPORT */ pbuf_header(pb, -(s16_t)sizeof(protocol)); @@ -874,7 +883,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { return; #endif /* PPP_IPV6_SUPPORT */ -#if VJ_SUPPORT && LWIP_TCP +#if VJ_SUPPORT case PPP_VJC_COMP: /* VJ compressed TCP */ /* * Clip off the VJ header and prepend the rebuilt TCP/IP header and @@ -902,7 +911,7 @@ void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { /* Something's wrong so drop it. */ PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); break; -#endif /* VJ_SUPPORT && LWIP_TCP */ +#endif /* VJ_SUPPORT */ default: { int i; @@ -994,13 +1003,10 @@ struct pbuf *ppp_singlebuf(struct pbuf *p) { * IPv4 and IPv6 packets from lwIP are sent, respectively, * with ppp_netif_output_ip4() and ppp_netif_output_ip6() * functions (which are callbacks of the netif PPP interface). - * - * RETURN: >= 0 Number of characters written - * -1 Failed to write to device */ err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { #if PRINTPKT_SUPPORT - ppp_dump_packet("sent", (unsigned char *)p->payload+2, p->len-2); + ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); #endif /* PRINTPKT_SUPPORT */ return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); } @@ -1084,7 +1090,7 @@ int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { LWIP_UNUSED_ARG(our_adr); LWIP_UNUSED_ARG(his_adr); - netif_set_addr(pcb->netif, IP4_ADDR_ANY, IP4_ADDR_BROADCAST, IP4_ADDR_ANY); + netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); return 1; } @@ -1139,12 +1145,12 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { nsa = dns_getserver(0); ip_addr_set_ip4_u32(&nsb, ns1); if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(0, IP_ADDR_ANY); + dns_setserver(0, IP4_ADDR_ANY); } nsa = dns_getserver(1); ip_addr_set_ip4_u32(&nsb, ns2); if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(1, IP_ADDR_ANY); + dns_setserver(1, IP4_ADDR_ANY); } return 1; } @@ -1213,7 +1219,7 @@ u32_t get_mask(u32_t addr) { #if 0 u32_t mask, nmask; - addr = htonl(addr); + addr = lwip_htonl(addr); if (IP_CLASSA(addr)) { /* determine network mask for address class */ nmask = IP_CLASSA_NET; } else if (IP_CLASSB(addr)) { @@ -1223,7 +1229,7 @@ u32_t get_mask(u32_t addr) { } /* class D nets are disallowed by bad_ip_adrs */ - mask = PP_HTONL(0xffffff00UL) | htonl(nmask); + mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); /* XXX * Scan through the system's network interfaces. @@ -1441,7 +1447,7 @@ int get_loop_output(void) { struct protocol_list { u_short proto; const char *name; -} protocol_list[] = { +} const protocol_list[] = { { 0x21, "IP" }, { 0x23, "OSI Network Layer" }, { 0x25, "Xerox NS IDP" }, @@ -1576,7 +1582,7 @@ struct protocol_list { * protocol_name - find a name for a PPP protocol. */ const char * protocol_name(int proto) { - struct protocol_list *lp; + const struct protocol_list *lp; for (lp = protocol_list; lp->proto != 0; ++lp) { if (proto == lp->proto) { diff --git a/src/netif/ppp/pppoe.c b/src/netif/ppp/pppoe.c index 348129ac..ed061c31 100644 --- a/src/netif/ppp/pppoe.c +++ b/src/netif/ppp/pppoe.c @@ -81,6 +81,7 @@ #include "lwip/stats.h" #include "lwip/snmp.h" +#include "netif/ethernet.h" #include "netif/ppp/ppp_impl.h" #include "netif/ppp/lcp.h" #include "netif/ppp/ipcp.h" @@ -189,8 +190,6 @@ ppp_pcb *pppoe_create(struct netif *pppif, } memset(sc, 0, sizeof(struct pppoe_softc)); - /* changed to real address later */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->pcb = ppp; sc->sc_ethif = ethif; /* put the new interface at the head of the list */ @@ -323,10 +322,6 @@ pppoe_destroy(ppp_pcb *ppp, void *ctx) static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { struct pppoe_softc *sc; - if (session == 0) { - return NULL; - } - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { if (sc->sc_state == PPPOE_STATE_SESSION && sc->sc_session == session @@ -342,10 +337,6 @@ static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct net static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { struct pppoe_softc *sc, *t; - if (pppoe_softc_list == NULL) { - return NULL; - } - if (len != sizeof sc) { return NULL; } @@ -428,8 +419,8 @@ pppoe_disc_input(struct netif *netif, struct pbuf *pb) PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); goto done; } - session = ntohs(ph->session); - plen = ntohs(ph->plen); + session = lwip_ntohs(ph->session); + plen = lwip_ntohs(ph->plen); off += sizeof(*ph); if (plen + off > pb->len) { @@ -445,8 +436,8 @@ pppoe_disc_input(struct netif *netif, struct pbuf *pb) sc = NULL; while (off + sizeof(pt) <= pb->len) { MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); - tag = ntohs(pt.tag); - len = ntohs(pt.len); + tag = lwip_ntohs(pt.tag); + len = lwip_ntohs(pt.len); if (off + sizeof(pt) + len > pb->len) { PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); goto done; @@ -689,7 +680,7 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb) goto drop; } - session = ntohs(ph->session); + session = lwip_ntohs(ph->session); sc = pppoe_find_softc_by_session(session, netif); if (sc == NULL) { #ifdef PPPOE_TERM_UNKNOWN_SESSIONS @@ -699,7 +690,7 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb) goto drop; } - plen = ntohs(ph->plen); + plen = lwip_ntohs(ph->plen); if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { /* bail out */ @@ -731,11 +722,6 @@ pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) u16_t etype; err_t res; - if (!sc->sc_ethif) { - pbuf_free(pb); - return ERR_IF; - } - /* make room for Ethernet header - should not fail */ if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { /* bail out */ @@ -746,7 +732,7 @@ pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) } ethhdr = (struct eth_hdr *)pb->payload; etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; - ethhdr->type = htons(etype); + ethhdr->type = lwip_htons(etype); MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); @@ -773,10 +759,6 @@ pppoe_send_padi(struct pppoe_softc *sc) int l1 = 0, l2 = 0; /* XXX: gcc */ #endif /* PPPOE_TODO */ - if (sc->sc_state >PPPOE_STATE_PADI_SENT) { - PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); - } - /* 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 */ #ifdef PPPOE_TODO @@ -900,7 +882,7 @@ pppoe_timeout(void *arg) static err_t pppoe_connect(ppp_pcb *ppp, void *ctx) { - int err; + err_t err; struct pppoe_softc *sc = (struct pppoe_softc *)ctx; lcp_options *lcp_wo; lcp_options *lcp_ao; @@ -909,15 +891,12 @@ pppoe_connect(ppp_pcb *ppp, void *ctx) ipcp_options *ipcp_ao; #endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - if (sc->sc_state != PPPOE_STATE_INITIAL) { - return EBUSY; - } - - /* stop any timer */ - sys_untimeout(pppoe_timeout, sc); sc->sc_session = 0; + sc->sc_ac_cookie_len = 0; sc->sc_padi_retried = 0; sc->sc_padr_retried = 0; + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); #ifdef PPPOE_SERVER /* wait PADI if IFF_PASSIVE */ if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { @@ -925,8 +904,6 @@ pppoe_connect(ppp_pcb *ppp, void *ctx) } #endif - ppp_link_start(ppp); - lcp_wo = &ppp->lcp_wantoptions; lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ lcp_wo->neg_asyncmap = 0; @@ -966,28 +943,21 @@ pppoe_disconnect(ppp_pcb *ppp, void *ctx) { struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - if (sc->sc_state < PPPOE_STATE_SESSION) { - return; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + if (sc->sc_state == PPPOE_STATE_SESSION) { + pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); } - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); - - /* cleanup softc */ + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppoe_timeout, sc); sc->sc_state = PPPOE_STATE_INITIAL; - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_ac_cookie_len = 0; #ifdef PPPOE_SERVER if (sc->sc_hunique) { mem_free(sc->sc_hunique); - sc->sc_hunique = NULL; + sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ } - sc->sc_hunique_len = 0; + sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ #endif - sc->sc_session = 0; - sc->sc_padi_retried = 0; - sc->sc_padr_retried = 0; - ppp_link_end(ppp); /* notify upper layers */ return; } @@ -997,15 +967,7 @@ static void pppoe_abort_connect(struct pppoe_softc *sc) { PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - - /* clear connection state */ sc->sc_state = PPPOE_STATE_INITIAL; - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_ac_cookie_len = 0; - sc->sc_session = 0; - sc->sc_padi_retried = 0; - sc->sc_padr_retried = 0; - ppp_link_failed(sc->pcb); /* notify upper layers */ } @@ -1020,10 +982,6 @@ pppoe_send_padr(struct pppoe_softc *sc) size_t l1 = 0; /* XXX: gcc */ #endif /* PPPOE_TODO */ - if (sc->sc_state != PPPOE_STATE_PADR_SENT) { - return ERR_CONN; - } - len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ #ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ @@ -1106,10 +1064,6 @@ pppoe_send_pado(struct pppoe_softc *sc) u8_t *p; size_t len; - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - return ERR_CONN; - } - /* calc length */ len = 0; /* include ac_cookie */ @@ -1140,10 +1094,6 @@ pppoe_send_pads(struct pppoe_softc *sc) u8_t *p; size_t len, l1 = 0; /* XXX: gcc */ - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - return ERR_CONN; - } - sc->sc_session = mono_time.tv_sec % 0xff + 1; /* calc length */ len = 0; @@ -1181,13 +1131,6 @@ pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) u8_t *p; size_t len; - /* are we ready to process data yet? */ - if (sc->sc_state < PPPOE_STATE_SESSION) { - /*sppp_flush(&sc->sc_sppp.pp_if);*/ - pbuf_free(pb); - return ERR_CONN; - } - len = pb->tot_len; /* make room for PPPoE header - should not fail */ @@ -1242,18 +1185,8 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message) /* stop timer */ sys_untimeout(pppoe_timeout, sc); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); - /* fix our state */ sc->sc_state = PPPOE_STATE_INITIAL; - - /* notify upper layers */ - ppp_link_end(sc->pcb); /* /!\ dangerous /!\ */ - - /* clean up softc */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_ac_cookie_len = 0; - sc->sc_session = 0; - sc->sc_padi_retried = 0; - sc->sc_padr_retried = 0; + ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */ } #endif /* UNUSED */ #endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/src/netif/ppp/pppol2tp.c b/src/netif/ppp/pppol2tp.c index ae5be762..c215cff6 100644 --- a/src/netif/ppp/pppol2tp.c +++ b/src/netif/ppp/pppol2tp.c @@ -81,7 +81,6 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); static void pppol2tp_timeout(void *arg); static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); -static void pppol2tp_clear(pppol2tp_pcb *l2tp); static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); @@ -262,13 +261,15 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) { ipcp_options *ipcp_ao; #endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - if (l2tp->phase != PPPOL2TP_STATE_INITIAL) { - return ERR_VAL; - } - - pppol2tp_clear(l2tp); - - ppp_link_start(ppp); + l2tp->tunnel_port = l2tp->remote_port; + l2tp->our_ns = 0; + l2tp->peer_nr = 0; + l2tp->peer_ns = 0; + l2tp->source_tunnel_id = 0; + l2tp->remote_tunnel_id = 0; + l2tp->source_session_id = 0; + l2tp->remote_session_id = 0; + /* l2tp->*_retried are cleared when used */ lcp_wo = &ppp->lcp_wantoptions; lcp_wo->mru = PPPOL2TP_DEFMRU; @@ -302,7 +303,7 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) { udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); } else #endif /* LWIP_IPV6 */ - udp_bind(l2tp->udp, IP_ADDR_ANY, 0); + udp_bind(l2tp->udp, IP4_ADDR_ANY, 0); #if PPPOL2TP_AUTH_SUPPORT /* Generate random vector */ @@ -328,14 +329,12 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) { static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - if (l2tp->phase < PPPOL2TP_STATE_DATA) { - return; - } - l2tp->our_ns++; pppol2tp_send_stopccn(l2tp, l2tp->our_ns); - pppol2tp_clear(l2tp); + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppol2tp_timeout, l2tp); + l2tp->phase = PPPOL2TP_STATE_INITIAL; ppp_link_end(ppp); /* notify upper layers */ } @@ -346,6 +345,7 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const u8_t *inp; LWIP_UNUSED_ARG(pcb); + /* we can't unbound a UDP pcb, thus we can still receive UDP frames after the link is closed */ if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { goto free_and_return; } @@ -772,24 +772,8 @@ static void pppol2tp_timeout(void *arg) { /* Connection attempt aborted */ static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); - pppol2tp_clear(l2tp); - ppp_link_failed(l2tp->ppp); /* notify upper layers */ -} - -/* Reset L2TP control block to its initial state */ -static void pppol2tp_clear(pppol2tp_pcb *l2tp) { - /* stop any timer */ - sys_untimeout(pppol2tp_timeout, l2tp); l2tp->phase = PPPOL2TP_STATE_INITIAL; - l2tp->tunnel_port = l2tp->remote_port; - l2tp->our_ns = 0; - l2tp->peer_nr = 0; - l2tp->peer_ns = 0; - l2tp->source_tunnel_id = 0; - l2tp->remote_tunnel_id = 0; - l2tp->source_session_id = 0; - l2tp->remote_session_id = 0; - /* l2tp->*_retried are cleared when used */ + ppp_link_failed(l2tp->ppp); /* notify upper layers */ } /* Initiate a new tunnel */ @@ -1113,12 +1097,6 @@ static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { u8_t *p; - /* are we ready to process data yet? */ - if (l2tp->phase < PPPOL2TP_STATE_DATA) { - pbuf_free(pb); - return ERR_CONN; - } - /* make room for L2TP header - should not fail */ if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { /* bail out */ diff --git a/src/netif/ppp/pppos.c b/src/netif/ppp/pppos.c index 006971d9..5220ed30 100644 --- a/src/netif/ppp/pppos.c +++ b/src/netif/ppp/pppos.c @@ -309,7 +309,6 @@ pppos_connect(ppp_pcb *ppp, void *ctx) pppos_input_free_current_packet(pppos); #endif /* PPP_INPROC_IRQ_SAFE */ - ppp_link_start(ppp); /* reset PPPoS control block to its initial state */ memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); @@ -343,7 +342,6 @@ pppos_listen(ppp_pcb *ppp, void *ctx) pppos_input_free_current_packet(pppos); #endif /* PPP_INPROC_IRQ_SAFE */ - ppp_link_start(ppp); /* reset PPPoS control block to its initial state */ memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); @@ -406,9 +404,9 @@ pppos_destroy(ppp_pcb *ppp, void *ctx) #if !NO_SYS && !PPP_INPROC_IRQ_SAFE /** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. * - * @param pcb PPP descriptor index, returned by pppos_create() - * @param data received data - * @param len length of received data + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data */ err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) @@ -460,9 +458,9 @@ PACK_STRUCT_END /** Pass received raw characters to PPPoS to be decoded. * - * @param pcb PPP descriptor index, returned by pppos_create() - * @param data received data - * @param len length of received data + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data */ void pppos_input(ppp_pcb *ppp, u8_t *s, int l) @@ -787,9 +785,9 @@ pppos_input_drop(pppos_pcb *pppos) PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); } pppos_input_free_current_packet(pppos); -#if VJ_SUPPORT && LWIP_TCP +#if VJ_SUPPORT vj_uncompress_err(&pppos->ppp->vj_comp); -#endif /* VJ_SUPPORT && LWIP_TCP */ +#endif /* VJ_SUPPORT */ LINK_STATS_INC(link.drop); MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); diff --git a/src/netif/ppp/utils.c b/src/netif/ppp/utils.c index 5b14ac59..a5ae86f0 100644 --- a/src/netif/ppp/utils.c +++ b/src/netif/ppp/utils.c @@ -267,7 +267,7 @@ int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { #endif /* do we always have strerror() in embedded ? */ case 'I': ip = va_arg(args, u32_t); - ip = ntohl(ip); + ip = lwip_ntohl(ip); ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); str = num; @@ -702,24 +702,20 @@ void ppp_dbglog(const char *fmt, ...) { * ppp_dump_packet - print out a packet in readable form if it is interesting. * Assumes len >= PPP_HDRLEN. */ -void ppp_dump_packet(const char *tag, unsigned char *p, int len) { +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { int proto; /* - * don't print IPv4 and IPv6 packets. + * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. */ proto = (p[0] << 8) + p[1]; - if (proto == PPP_IP) + if (proto < 0xC000 && (proto & ~0x8000) == proto) return; -#if PPP_IPV6_SUPPORT - if (proto == PPP_IPV6) - return; -#endif /* - * don't print LCP echo request/reply packets if the link is up. + * don't print valid LCP echo request/reply packets if the link is up. */ - if (proto == PPP_LCP && len >= 2 + HEADERLEN) { + if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { unsigned char *lcp = p + 2; int l = (lcp[2] << 8) + lcp[3]; diff --git a/src/netif/ppp/vj.c b/src/netif/ppp/vj.c index b297c78d..168c3400 100644 --- a/src/netif/ppp/vj.c +++ b/src/netif/ppp/vj.c @@ -29,7 +29,7 @@ */ #include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP /* don't build if not configured for use in lwipopts.h */ +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ #include "netif/ppp/ppp_impl.h" #include "netif/ppp/pppdebug.h" @@ -95,32 +95,32 @@ vj_compress_init(struct vjcompress *comp) #define DECODEL(f) { \ if (*cp == 0) {\ - u32_t tmp_ = ntohl(f) + ((cp[1] << 8) | cp[2]); \ - (f) = htonl(tmp_); \ + u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = lwip_htonl(tmp_); \ cp += 3; \ } else { \ - u32_t tmp_ = ntohl(f) + (u32_t)*cp++; \ - (f) = htonl(tmp_); \ + u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ + (f) = lwip_htonl(tmp_); \ } \ } #define DECODES(f) { \ if (*cp == 0) {\ - u16_t tmp_ = ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ - (f) = htons(tmp_); \ + u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ + (f) = lwip_htons(tmp_); \ cp += 3; \ } else { \ - u16_t tmp_ = ntohs(f) + (u16_t)*cp++; \ - (f) = htons(tmp_); \ + u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ + (f) = lwip_htons(tmp_); \ } \ } #define DECODEU(f) { \ if (*cp == 0) {\ - (f) = htons(((u16_t)cp[1] << 8) | cp[2]); \ + (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ cp += 3; \ } else { \ - (f) = htons((u16_t)*cp++); \ + (f) = lwip_htons((u16_t)*cp++); \ } \ } @@ -306,7 +306,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) * needed in this section of code). */ if (TCPH_FLAGS(th) & TCP_URG) { - deltaS = ntohs(th->urgp); + deltaS = lwip_ntohs(th->urgp); ENCODEZ(deltaS); changes |= NEW_U; } else if (th->urgp != oth->urgp) { @@ -317,12 +317,12 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) goto uncompressed; } - if ((deltaS = (u16_t)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { + if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { ENCODE(deltaS); changes |= NEW_W; } - if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { + if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { if (deltaL > 0xffff) { goto uncompressed; } @@ -331,7 +331,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) changes |= NEW_A; } - if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { + if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { if (deltaL > 0xffff) { goto uncompressed; } @@ -351,7 +351,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) * in case the other side missed the compressed version. */ if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && - ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { break; } /* no break */ @@ -366,7 +366,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) goto uncompressed; case NEW_S|NEW_A: - if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { /* special case for echoed terminal traffic */ changes = SPECIAL_I; cp = new_seq; @@ -374,7 +374,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) break; case NEW_S: - if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { /* special case for data xfer */ changes = SPECIAL_D; cp = new_seq; @@ -384,7 +384,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) break; } - deltaS = (u16_t)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); + deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); if (deltaS != 1) { ENCODEZ(deltaS); changes |= NEW_I; @@ -396,7 +396,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) * Grab the cksum before we overwrite it below. Then update our * state with this packet's header. */ - deltaA = ntohs(th->chksum); + deltaA = lwip_ntohs(th->chksum); MEMCPY(&cs->cs_ip, ip, hlen); /* @@ -538,7 +538,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) cs = &comp->rstate[comp->last_recv]; hlen = IPH_HL(&cs->cs_ip) << 2; th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; - th->chksum = htons((*cp << 8) | cp[1]); + th->chksum = lwip_htons((*cp << 8) | cp[1]); cp += 2; if (changes & TCP_PUSH_BIT) { TCPH_SET_FLAG(th, TCP_PSH); @@ -549,19 +549,19 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) switch (changes & SPECIALS_MASK) { case SPECIAL_I: { - u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->ackno) + i; - th->ackno = htonl(tmp); - tmp = ntohl(th->seqno) + i; - th->seqno = htonl(tmp); + tmp = lwip_ntohl(th->ackno) + i; + th->ackno = lwip_htonl(tmp); + tmp = lwip_ntohl(th->seqno) + i; + th->seqno = lwip_htonl(tmp); } break; case SPECIAL_D: /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - th->seqno = htonl(tmp); + tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = lwip_htonl(tmp); break; default: @@ -585,8 +585,8 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) if (changes & NEW_I) { DECODES(cs->cs_ip._id); } else { - IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); - IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); + IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); } /* @@ -607,9 +607,9 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) #if BYTE_ORDER == LITTLE_ENDIAN tmp = n0->tot_len - vjlen + cs->cs_hlen; - IPH_LEN_SET(&cs->cs_ip, htons((u16_t)tmp)); + IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); #else - IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); + IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); #endif /* recompute the ip header checksum */ @@ -692,4 +692,4 @@ bad: return (-1); } -#endif /* PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP */ +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/src/netif/slipif.c b/src/netif/slipif.c index f6c5d4b7..6eb83c35 100644 --- a/src/netif/slipif.c +++ b/src/netif/slipif.c @@ -42,10 +42,10 @@ /** * @defgroup slipif SLIP netif * @ingroup addons - * + * * 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 @@ -304,7 +304,7 @@ slipif_rxbyte(struct netif *netif, u8_t c) /** Like slipif_rxbyte, but passes completed packets to netif->input * * @param netif The lwip network interface structure for this slipif - * @param data received character + * @param c received character */ static void slipif_rxbyte_input(struct netif *netif, u8_t c) diff --git a/test/unit/core/test_mem.h b/test/unit/core/test_mem.h index a85bccb4..325134c3 100644 --- a/test/unit/core/test_mem.h +++ b/test/unit/core/test_mem.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_MEM_H__ -#define LWIP_HDR_TEST_MEM_H__ +#ifndef LWIP_HDR_TEST_MEM_H +#define LWIP_HDR_TEST_MEM_H #include "../lwip_check.h" diff --git a/test/unit/core/test_pbuf.h b/test/unit/core/test_pbuf.h index 82531570..da7730a4 100644 --- a/test/unit/core/test_pbuf.h +++ b/test/unit/core/test_pbuf.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_PBUF_H__ -#define LWIP_HDR_TEST_PBUF_H__ +#ifndef LWIP_HDR_TEST_PBUF_H +#define LWIP_HDR_TEST_PBUF_H #include "../lwip_check.h" diff --git a/test/unit/dhcp/test_dhcp.c b/test/unit/dhcp/test_dhcp.c index 0d0e81af..68f28819 100644 --- a/test/unit/dhcp/test_dhcp.c +++ b/test/unit/dhcp/test_dhcp.c @@ -2,7 +2,9 @@ #include "lwip/netif.h" #include "lwip/dhcp.h" -#include "netif/etharp.h" +#include "lwip/prot/dhcp.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" struct netif net_test; @@ -124,6 +126,8 @@ static enum tcase { static int debug = 0; static void setdebug(int a) {debug = a;} +#define netif_dhcp_data(netif) ((struct dhcp*)(netif)->client_data[LWIP_NETIF_CLIENT_DATA_INDEX_DHCP]) + static int tick = 0; static void tick_lwip(void) { @@ -447,7 +451,7 @@ START_TEST(test_dhcp) dhcp_start(&net_test); fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ memcpy(&dhcp_offer[46], &xid, 4); send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); @@ -457,17 +461,17 @@ START_TEST(test_dhcp) fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */ - xid = htonl(net_test.dhcp->xid); + xid = htonl(netif_dhcp_data(&net_test)->xid); memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */ - xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ memcpy(&dhcp_ack[46], &xid, 4); send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */ - xid = htonl(net_test.dhcp->xid); /* xid updated */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); @@ -516,7 +520,7 @@ START_TEST(test_dhcp_nak) dhcp_start(&net_test); fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ memcpy(&dhcp_offer[46], &xid, 4); send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); @@ -526,17 +530,17 @@ START_TEST(test_dhcp_nak) fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(net_test.dhcp->xid); + xid = htonl(netif_dhcp_data(&net_test)->xid); memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); fail_unless(txpacket == 2); /* DHCP request sent */ - xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ memcpy(&dhcp_ack[46], &xid, 4); send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(net_test.dhcp->xid); /* xid updated */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); @@ -741,13 +745,13 @@ START_TEST(test_dhcp_relayed) fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(net_test.dhcp->xid); + xid = htonl(netif_dhcp_data(&net_test)->xid); memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */ send_pkt(&net_test, relay_offer, sizeof(relay_offer)); /* request sent? */ fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket); - xid = htonl(net_test.dhcp->xid); /* xid updated */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */ send_pkt(&net_test, relay_ack1, sizeof(relay_ack1)); @@ -783,7 +787,7 @@ START_TEST(test_dhcp_relayed) fail_unless(txpacket == 7, "txpacket = %d", txpacket); fail_unless(netif_is_up(&net_test)); - xid = htonl(net_test.dhcp->xid); /* xid updated */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */ send_pkt(&net_test, relay_ack2, sizeof(relay_ack2)); @@ -872,7 +876,7 @@ START_TEST(test_dhcp_nak_no_endmarker) dhcp_start(&net_test); fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ memcpy(&dhcp_offer[46], &xid, 4); send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); @@ -882,19 +886,19 @@ START_TEST(test_dhcp_nak_no_endmarker) fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(net_test.dhcp->xid); + xid = htonl(netif_dhcp_data(&net_test)->xid); memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - fail_unless(net_test.dhcp->state == DHCP_STATE_REQUESTING); + fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(net_test.dhcp->xid); /* xid updated */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */ send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker)); /* NAK should put us in another state for a while, no other way detecting it */ - fail_unless(net_test.dhcp->state != DHCP_STATE_REQUESTING); + fail_unless(netif_dhcp_data(&net_test)->state != DHCP_STATE_REQUESTING); netif_remove(&net_test); } diff --git a/test/unit/dhcp/test_dhcp.h b/test/unit/dhcp/test_dhcp.h index 480aab9b..0d88fa1b 100644 --- a/test/unit/dhcp/test_dhcp.h +++ b/test/unit/dhcp/test_dhcp.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_DHCP_H__ -#define LWIP_HDR_TEST_DHCP_H__ +#ifndef LWIP_HDR_TEST_DHCP_H +#define LWIP_HDR_TEST_DHCP_H #include "../lwip_check.h" diff --git a/test/unit/etharp/test_etharp.c b/test/unit/etharp/test_etharp.c index ba9a40dc..59d73b9b 100644 --- a/test/unit/etharp/test_etharp.c +++ b/test/unit/etharp/test_etharp.c @@ -1,7 +1,8 @@ #include "test_etharp.h" #include "lwip/udp.h" -#include "netif/etharp.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" #include "lwip/stats.h" #if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS diff --git a/test/unit/etharp/test_etharp.h b/test/unit/etharp/test_etharp.h index fac7c9cf..2dd772d8 100644 --- a/test/unit/etharp/test_etharp.h +++ b/test/unit/etharp/test_etharp.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_ETHARP_H__ -#define LWIP_HDR_TEST_ETHARP_H__ +#ifndef LWIP_HDR_TEST_ETHARP_H +#define LWIP_HDR_TEST_ETHARP_H #include "../lwip_check.h" diff --git a/test/unit/lwip_check.h b/test/unit/lwip_check.h index 2126e2ff..0c218d1d 100644 --- a/test/unit/lwip_check.h +++ b/test/unit/lwip_check.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_LWIP_CHECK_H__ -#define LWIP_HDR_LWIP_CHECK_H__ +#ifndef LWIP_HDR_LWIP_CHECK_H +#define LWIP_HDR_LWIP_CHECK_H /* Common header file for lwIP unit tests using the check framework */ @@ -34,4 +34,4 @@ Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun se int lwip_unittests_run(void) #endif -#endif /* LWIP_HDR_LWIP_CHECK_H__ */ +#endif /* LWIP_HDR_LWIP_CHECK_H */ diff --git a/test/unit/lwip_unittests.c b/test/unit/lwip_unittests.c index b702884a..46fd4308 100644 --- a/test/unit/lwip_unittests.c +++ b/test/unit/lwip_unittests.c @@ -7,6 +7,7 @@ #include "core/test_pbuf.h" #include "etharp/test_etharp.h" #include "dhcp/test_dhcp.h" +#include "mdns/test_mdns.h" #include "lwip/init.h" @@ -42,7 +43,8 @@ int main(void) mem_suite, pbuf_suite, etharp_suite, - dhcp_suite + dhcp_suite, + mdns_suite }; size_t num = sizeof(suites)/sizeof(void*); LWIP_ASSERT("No suites defined", num > 0); diff --git a/test/unit/lwipopts.h b/test/unit/lwipopts.h index 5cda4315..25252b42 100644 --- a/test/unit/lwipopts.h +++ b/test/unit/lwipopts.h @@ -29,8 +29,8 @@ * Author: Simon Goldschmidt * */ -#ifndef LWIP_HDR_LWIPOPTS_H__ -#define LWIP_HDR_LWIPOPTS_H__ +#ifndef LWIP_HDR_LWIPOPTS_H +#define LWIP_HDR_LWIPOPTS_H /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ #define NO_SYS 1 @@ -51,7 +51,12 @@ #define TCP_RCV_SCALE 0 #define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ +/* Enable IGMP and MDNS for MDNS tests */ +#define LWIP_IGMP 1 +#define LWIP_MDNS_RESPONDER 1 +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) + /* Minimal changes to opt.h required for etharp unit tests: */ #define ETHARP_SUPPORT_STATIC_ENTRIES 1 -#endif /* LWIP_HDR_LWIPOPTS_H__ */ +#endif /* LWIP_HDR_LWIPOPTS_H */ diff --git a/test/unit/mdns/test_mdns.c b/test/unit/mdns/test_mdns.c new file mode 100644 index 00000000..9cff0fd7 --- /dev/null +++ b/test/unit/mdns/test_mdns.c @@ -0,0 +1,888 @@ +/* + * 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 + * + * Please coordinate changes and requests with Erik Ekman + * + * + */ + +#include "test_mdns.h" + +#include "lwip/pbuf.h" +#include "lwip/apps/mdns.h" +#include "lwip/apps/mdns_priv.h" + +START_TEST(readname_basic) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(readname_anydata) +{ + static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(readname_short_buf) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_long_label) +{ static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', + 0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_overflow) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_earlier) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab, + /* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c, + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 20, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_earlier_jump) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, + /* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10, + /* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16, + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0x18, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_maxdepth) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, + /* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03, + /* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10, + /* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00, + /* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0, + /* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28, + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's', + 0x04, 'n', 'a', 'm', 'e', 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0x30, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_later) +{ + static const u8_t data[] = { + /* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40, + /* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab, + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == 13); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_half_jump) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_toolong) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_loop_label) +{ + static const u8_t data[] = { + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 10, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_loop_jump) +{ + static const u8_t data[] = { + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 10, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(add_label_basic) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; + struct mdns_domain domain; + err_t res; + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(add_label_long_label) +{ + static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-"; + struct mdns_domain domain; + err_t res; + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong)); + fail_unless(res == ERR_VAL); +} +END_TEST + +START_TEST(add_label_full) +{ + static const char *label = "0123456789abcdef0123456789abcdef"; + struct mdns_domain domain; + err_t res; + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 33); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 66); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 99); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 132); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 165); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 198); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 25); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 24); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 23); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 255); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 256); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 256); +} +END_TEST + +START_TEST(domain_eq_basic) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00, + }; + struct mdns_domain domain1, domain2; + err_t res; + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain1.length == sizeof(data)); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_diff) +{ + struct mdns_domain domain1, domain2; + err_t res; + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "base", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_if(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_case) +{ + struct mdns_domain domain1, domain2; + err_t res; + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "MulTI", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "casT", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_anydata) +{ + static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 }; + static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf }; + struct mdns_domain domain1, domain2; + err_t res; + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "casT", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_length) +{ + struct mdns_domain domain1, domain2; + err_t res; + + memset(&domain1, 0, sizeof(domain1)); + memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(compress_full_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 2 */ + fail_unless(length == 0); + fail_unless(offset == 2); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_full_match_subset) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 5 */ + fail_unless(length == 0); + fail_unless(offset == 5); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_full_match_jump) +{ + static const u8_t data[] = { + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, + /* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 0x20; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 0x20 */ + fail_unless(length == 0); + fail_unless(offset == 0x20); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_no_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write all bytes, no jump */ + fail_unless(length == domain.length); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_2nd_label) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "lwip", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 5 bytes, then a jump to addr 9 */ + fail_unless(length == 5); + fail_unless(offset == 9); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_2nd_label_short) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 5 bytes, then a jump to addr 7 */ + fail_unless(length == 7); + fail_unless(offset == 7); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_jump_to_jump) +{ + static const u8_t data[] = { + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, + /* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15, + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 0x20; + length = mdns_compress_domain(p, &offset, &domain); + /* Dont compress if jump would be to a jump */ + fail_unless(length == domain.length); + + offset = 0x10; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 7 bytes, then a jump to addr 0x15 */ + fail_unless(length == 7); + fail_unless(offset == 0x15); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_long_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + fail_unless(length == domain.length); + + pbuf_free(p); +} +END_TEST + +Suite* mdns_suite(void) +{ + testfunc tests[] = { + TESTFUNC(readname_basic), + TESTFUNC(readname_anydata), + TESTFUNC(readname_short_buf), + TESTFUNC(readname_long_label), + TESTFUNC(readname_overflow), + TESTFUNC(readname_jump_earlier), + TESTFUNC(readname_jump_earlier_jump), + TESTFUNC(readname_jump_maxdepth), + TESTFUNC(readname_jump_later), + TESTFUNC(readname_half_jump), + TESTFUNC(readname_jump_toolong), + TESTFUNC(readname_jump_loop_label), + TESTFUNC(readname_jump_loop_jump), + + TESTFUNC(add_label_basic), + TESTFUNC(add_label_long_label), + TESTFUNC(add_label_full), + + TESTFUNC(domain_eq_basic), + TESTFUNC(domain_eq_diff), + TESTFUNC(domain_eq_case), + TESTFUNC(domain_eq_anydata), + TESTFUNC(domain_eq_length), + + TESTFUNC(compress_full_match), + TESTFUNC(compress_full_match_subset), + TESTFUNC(compress_full_match_jump), + TESTFUNC(compress_no_match), + TESTFUNC(compress_2nd_label), + TESTFUNC(compress_2nd_label_short), + TESTFUNC(compress_jump_to_jump), + TESTFUNC(compress_long_match), + }; + return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL); +} diff --git a/test/unit/mdns/test_mdns.h b/test/unit/mdns/test_mdns.h new file mode 100644 index 00000000..c3df3391 --- /dev/null +++ b/test/unit/mdns/test_mdns.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_MDNS_H__ +#define LWIP_HDR_TEST_MDNS_H__ + +#include "../lwip_check.h" + +Suite* mdns_suite(void); + +#endif diff --git a/test/unit/tcp/tcp_helper.h b/test/unit/tcp/tcp_helper.h index 4119f37e..04974818 100644 --- a/test/unit/tcp/tcp_helper.h +++ b/test/unit/tcp/tcp_helper.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TCP_HELPER_H__ -#define LWIP_HDR_TCP_HELPER_H__ +#ifndef LWIP_HDR_TCP_HELPER_H +#define LWIP_HDR_TCP_HELPER_H #include "../lwip_check.h" #include "lwip/arch.h" diff --git a/test/unit/tcp/test_tcp.c b/test/unit/tcp/test_tcp.c index 1b89f651..bfcfa1d9 100644 --- a/test/unit/tcp/test_tcp.c +++ b/test/unit/tcp/test_tcp.c @@ -206,7 +206,7 @@ START_TEST(test_tcp_fast_retx_recover) char data3[] = { 9, 10, 11, 12}; char data4[] = {13, 14, 15, 16}; char data5[] = {17, 18, 19, 20}; - char data6[] = {21, 22, 23, 24}; + char data6[TCP_MSS] = {21, 22, 23, 24}; ip_addr_t remote_ip, local_ip, netmask; u16_t remote_port = 0x100, local_port = 0x101; err_t err; diff --git a/test/unit/tcp/test_tcp.h b/test/unit/tcp/test_tcp.h index ea739eba..f28ee565 100644 --- a/test/unit/tcp/test_tcp.h +++ b/test/unit/tcp/test_tcp.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_TCP_H__ -#define LWIP_HDR_TEST_TCP_H__ +#ifndef LWIP_HDR_TEST_TCP_H +#define LWIP_HDR_TEST_TCP_H #include "../lwip_check.h" diff --git a/test/unit/tcp/test_tcp_oos.c b/test/unit/tcp/test_tcp_oos.c index 98f7098d..be611722 100644 --- a/test/unit/tcp/test_tcp_oos.c +++ b/test/unit/tcp/test_tcp_oos.c @@ -454,7 +454,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ) } END_TEST -static char data_full_wnd[TCP_WND]; +static char data_full_wnd[TCP_WND + TCP_MSS]; /** create multiple segments and pass them to tcp_input with the first segment missing * to simulate overruning the rxwin with ooseq queueing enabled */ diff --git a/test/unit/tcp/test_tcp_oos.h b/test/unit/tcp/test_tcp_oos.h index 1cb8650f..5b82013b 100644 --- a/test/unit/tcp/test_tcp_oos.h +++ b/test/unit/tcp/test_tcp_oos.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_TCP_OOS_H__ -#define LWIP_HDR_TEST_TCP_OOS_H__ +#ifndef LWIP_HDR_TEST_TCP_OOS_H +#define LWIP_HDR_TEST_TCP_OOS_H #include "../lwip_check.h" diff --git a/test/unit/udp/test_udp.h b/test/unit/udp/test_udp.h index eb14354b..5426bf42 100644 --- a/test/unit/udp/test_udp.h +++ b/test/unit/udp/test_udp.h @@ -1,5 +1,5 @@ -#ifndef LWIP_HDR_TEST_UDP_H__ -#define LWIP_HDR_TEST_UDP_H__ +#ifndef LWIP_HDR_TEST_UDP_H +#define LWIP_HDR_TEST_UDP_H #include "../lwip_check.h"