未验证 提交 e6ab9dc2 编写于 作者: O openharmony_ci 提交者: Gitee

!40 升级到2.1.3

Merge pull request !40 from Yangys/master
......@@ -16,4 +16,4 @@
/test/fuzz/output
/test/fuzz/lwip_fuzz
/test/fuzz/.depend
/build
\ No newline at end of file
/build
INTRODUCTION
lwIP is a small independent implementation of the TCP/IP protocol suite.
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
while still having a full scale TCP. This making lwIP suitable for use
in embedded systems with tens of kilobytes of free RAM and room for
around 40 kilobytes of code ROM.
lwIP was originally developed by Adam Dunkels at the Computer and Networks
Architectures (CNA) lab at the Swedish Institute of Computer Science (SICS)
and is now developed and maintained by a worldwide network of developers.
FEATURES
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
multiple network interfaces
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
* IGMP (Internet Group Management Protocol) for multicast traffic management
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
RFC 2710. No support for MLDv2
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
(Address autoconfiguration)
* DHCP, AutoIP/APIPA (Zeroconf) and (stateless) DHCPv6
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
fast recovery/fast retransmit and sending SACKs
* raw/native API for enhanced performance
* Optional Berkeley-like socket API
* TLS: optional layered TCP ("altcp") for nearly transparent TLS for any
TCP-based protocol (ported to mbedTLS) (see changelog for more info)
* PPPoS and PPPoE (Point-to-point protocol over Serial/Ethernet)
* DNS (Domain name resolver incl. mDNS)
* 6LoWPAN (via IEEE 802.15.4, BLE or ZEP)
APPLICATIONS
* HTTP server with SSI and CGI (HTTPS via altcp)
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol), v3 via altcp
* SNTP (Simple network time protocol)
* NetBIOS name service responder
* MDNS (Multicast DNS) responder
* iPerf server implementation
* MQTT client (TLS support via altcp)
LICENSE
lwIP is freely available under a BSD license.
DEVELOPMENT
lwIP has grown into an excellent TCP/IP stack for embedded devices,
and developers using the stack often submit bug fixes, improvements,
and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. Everyone can
help improve lwIP by use of Savannah's interface, Git and the
mailing list. A core team of developers will commit changes to the
Git source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
contributions (such as platform ports) are in the 'contrib' Git module.
See doc/savannah.txt for details on Git server access for users and
developers.
The current Git trees are web-browsable:
http://git.savannah.gnu.org/cgit/lwip.git
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/
Continuous integration builds (GCC, clang):
https://travis-ci.org/yarrick/lwip-merged
DOCUMENTATION
Self documentation of the source code is regularly extracted from the current
Git sources and is available from this web page:
http://www.nongnu.org/lwip/
There is now a constantly growing wiki about lwIP at
http://lwip.wikia.com/wiki/LwIP_Wiki
Also, there are mailing lists you can subscribe at
http://savannah.nongnu.org/mail/?group=lwip
plus searchable archives:
http://lists.nongnu.org/archive/html/lwip-users/
http://lists.nongnu.org/archive/html/lwip-devel/
lwIP was originally written by Adam Dunkels:
http://dunkels.com/adam/
Reading Adam's papers, the files in docs/, browsing the source code
documentation and browsing the mailing list archives is a good way to
become familiar with the design of lwIP.
Adam Dunkels <adam@sics.se>
Leon Woestenberg <leon.woestenberg@gmx.net>
......@@ -3,7 +3,7 @@
"Name" : "lwip",
"License" : "BSD 3-Clause License",
"License File" : "COPYING",
"Version Number" : "2.1.2",
"Version Number" : "2.1.3",
"Owner" : "wangmihu@huawei.com",
"Upstream URL" : "https://savannah.nongnu.org/projects/lwip/",
"Description" : "lwIP is a small independent implementation of the TCP/IP protocol suite that has been initially developed by Adam Dunkels. The focus of the lwIP TCP/IP implementation is to reduce resource usage while still having a full scale TCP. This makes lwIP suitable for use in embedded systems with tens of kilobytes of free RAM and room for around 40 kilobytes of code ROM."
......
......@@ -38,7 +38,7 @@ PROJECT_NAME = "lwIP"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "2.1.2"
PROJECT_NUMBER = "2.1.3"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
......
......@@ -204,6 +204,15 @@
* Read especially sections "Cache coherency" and "Buffer alignment".
*/
/**
* @page mem_err Debugging memory pool sizes
* If you have issues with lwIP and you are using memory pools, check that your pools
* are correctly sized.\n
* To debug pool sizes, \#define LWIP_STATS and MEMP_STATS to 1. Check the global variable
* lwip_stats.memp[] using a debugger. If the "err" member of a pool is > 0, the pool
* may be too small for your application and you need to increase its size.
*/
/**
* @page bugs Reporting bugs
* Please report bugs in the lwIP bug tracker at savannah.\n
......
# Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
LWIPDIR = "//third_party/lwip/src"
LWIP_INCLUDE_DIRS = [ "$LWIPDIR/include" ]
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES = [
"$LWIPDIR/core/init.c",
"$LWIPDIR/core/def.c",
"$LWIPDIR/core/dns.c",
"$LWIPDIR/core/inet_chksum.c",
"$LWIPDIR/core/ip.c",
"$LWIPDIR/core/mem.c",
"$LWIPDIR/core/memp.c",
"$LWIPDIR/core/netif.c",
"$LWIPDIR/core/pbuf.c",
"$LWIPDIR/core/raw.c",
"$LWIPDIR/core/stats.c",
"$LWIPDIR/core/sys.c",
"$LWIPDIR/core/altcp.c",
"$LWIPDIR/core/altcp_alloc.c",
"$LWIPDIR/core/altcp_tcp.c",
"$LWIPDIR/core/tcp.c",
"$LWIPDIR/core/tcp_in.c",
"$LWIPDIR/core/tcp_out.c",
"$LWIPDIR/core/timeouts.c",
"$LWIPDIR/core/udp.c",
]
CORE4FILES = [
"$LWIPDIR/core/ipv4/autoip.c",
"$LWIPDIR/core/ipv4/dhcp.c",
"$LWIPDIR/core/ipv4/etharp.c",
"$LWIPDIR/core/ipv4/icmp.c",
"$LWIPDIR/core/ipv4/igmp.c",
"$LWIPDIR/core/ipv4/ip4_frag.c",
"$LWIPDIR/core/ipv4/ip4.c",
"$LWIPDIR/core/ipv4/ip4_addr.c",
]
CORE6FILES = [
"$LWIPDIR/core/ipv6/dhcp6.c",
"$LWIPDIR/core/ipv6/ethip6.c",
"$LWIPDIR/core/ipv6/icmp6.c",
"$LWIPDIR/core/ipv6/inet6.c",
"$LWIPDIR/core/ipv6/ip6.c",
"$LWIPDIR/core/ipv6/ip6_addr.c",
"$LWIPDIR/core/ipv6/ip6_frag.c",
"$LWIPDIR/core/ipv6/mld6.c",
"$LWIPDIR/core/ipv6/nd6.c",
]
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES = [
"$LWIPDIR/api/api_lib.c",
"$LWIPDIR/api/api_msg.c",
"$LWIPDIR/api/err.c",
"$LWIPDIR/api/if_api.c",
"$LWIPDIR/api/netbuf.c",
"$LWIPDIR/api/netdb.c",
"$LWIPDIR/api/netifapi.c",
"$LWIPDIR/api/sockets.c",
"$LWIPDIR/api/tcpip.c",
]
# NETIFFILES: Files implementing various generic network interface functions
NETIFFILES = [
"$LWIPDIR/netif/ethernet.c",
"$LWIPDIR/netif/bridgeif.c",
"$LWIPDIR/netif/bridgeif_fdb.c",
"$LWIPDIR/netif/slipif.c",
]
# SIXLOWPAN: 6LoWPAN
SIXLOWPAN = [
"$LWIPDIR/netif/lowpan6_common.c",
"$LWIPDIR/netif/lowpan6.c",
"$LWIPDIR/netif/lowpan6_ble.c",
"$LWIPDIR/netif/zepif.c",
]
# PPPFILES: PPP
PPPFILES = [
"$LWIPDIR/netif/ppp/auth.c",
"$LWIPDIR/netif/ppp/ccp.c",
"$LWIPDIR/netif/ppp/chap-md5.c",
"$LWIPDIR/netif/ppp/chap_ms.c",
"$LWIPDIR/netif/ppp/chap-new.c",
"$LWIPDIR/netif/ppp/demand.c",
"$LWIPDIR/netif/ppp/eap.c",
"$LWIPDIR/netif/ppp/ecp.c",
"$LWIPDIR/netif/ppp/eui64.c",
"$LWIPDIR/netif/ppp/fsm.c",
"$LWIPDIR/netif/ppp/ipcp.c",
"$LWIPDIR/netif/ppp/ipv6cp.c",
"$LWIPDIR/netif/ppp/lcp.c",
"$LWIPDIR/netif/ppp/magic.c",
"$LWIPDIR/netif/ppp/mppe.c",
"$LWIPDIR/netif/ppp/multilink.c",
"$LWIPDIR/netif/ppp/ppp.c",
"$LWIPDIR/netif/ppp/pppapi.c",
"$LWIPDIR/netif/ppp/pppcrypt.c",
"$LWIPDIR/netif/ppp/pppoe.c",
"$LWIPDIR/netif/ppp/pppol2tp.c",
"$LWIPDIR/netif/ppp/pppos.c",
"$LWIPDIR/netif/ppp/upap.c",
"$LWIPDIR/netif/ppp/utils.c",
"$LWIPDIR/netif/ppp/vj.c",
"$LWIPDIR/netif/ppp/polarssl/arc4.c",
"$LWIPDIR/netif/ppp/polarssl/des.c",
"$LWIPDIR/netif/ppp/polarssl/md4.c",
"$LWIPDIR/netif/ppp/polarssl/md5.c",
"$LWIPDIR/netif/ppp/polarssl/sha1.c",
]
# LWIPNOAPPSFILES: All LWIP files without apps
LWIPNOAPPSFILES = COREFILES + CORE4FILES + CORE6FILES + APIFILES + NETIFFILES +
PPPFILES + SIXLOWPAN
# SNMPFILES: SNMPv2c agent
SNMPFILES = [
"$LWIPDIR/apps/snmp/snmp_asn1.c",
"$LWIPDIR/apps/snmp/snmp_core.c",
"$LWIPDIR/apps/snmp/snmp_mib2.c",
"$LWIPDIR/apps/snmp/snmp_mib2_icmp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_interfaces.c",
"$LWIPDIR/apps/snmp/snmp_mib2_ip.c",
"$LWIPDIR/apps/snmp/snmp_mib2_snmp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_system.c",
"$LWIPDIR/apps/snmp/snmp_mib2_tcp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_udp.c",
"$LWIPDIR/apps/snmp/snmp_snmpv2_framework.c",
"$LWIPDIR/apps/snmp/snmp_snmpv2_usm.c",
"$LWIPDIR/apps/snmp/snmp_msg.c",
"$LWIPDIR/apps/snmp/snmpv3.c",
"$LWIPDIR/apps/snmp/snmp_netconn.c",
"$LWIPDIR/apps/snmp/snmp_pbuf_stream.c",
"$LWIPDIR/apps/snmp/snmp_raw.c",
"$LWIPDIR/apps/snmp/snmp_scalar.c",
"$LWIPDIR/apps/snmp/snmp_table.c",
"$LWIPDIR/apps/snmp/snmp_threadsync.c",
"$LWIPDIR/apps/snmp/snmp_traps.c",
]
# HTTPFILES: HTTP server + client
HTTPFILES = [
"$LWIPDIR/apps/http/altcp_proxyconnect.c",
"$LWIPDIR/apps/http/fs.c",
"$LWIPDIR/apps/http/http_client.c",
"$LWIPDIR/apps/http/httpd.c",
]
# MAKEFSDATA: MAKEFSDATA HTTP server host utility
MAKEFSDATAFILES = [ "$LWIPDIR/apps/http/makefsdata/makefsdata.c" ]
# LWIPERFFILES: IPERF server
LWIPERFFILES = [ "$LWIPDIR/apps/lwiperf/lwiperf.c" ]
# SMTPFILES: SMTP client
SMTPFILES = [ "$LWIPDIR/apps/smtp/smtp.c" ]
# SNTPFILES: SNTP client
SNTPFILES = [ "$LWIPDIR/apps/sntp/sntp.c" ]
# MDNSFILES: MDNS responder
MDNSFILES = [ "$LWIPDIR/apps/mdns/mdns.c" ]
# NETBIOSNSFILES: NetBIOS name server
NETBIOSNSFILES = [ "$LWIPDIR/apps/netbiosns/netbiosns.c" ]
# TFTPFILES: TFTP server files
TFTPFILES = [ "$LWIPDIR/apps/tftp/tftp_server.c" ]
# MQTTFILES: MQTT client files
MQTTFILES = [ "$LWIPDIR/apps/mqtt/mqtt.c" ]
# MBEDTLS_FILES: MBEDTLS related files of lwIP rep
MBEDTLS_FILES = [
"$LWIPDIR/apps/altcp_tls/altcp_tls_mbedtls.c",
"$LWIPDIR/apps/altcp_tls/altcp_tls_mbedtls_mem.c",
"$LWIPDIR/apps/snmp/snmpv3_mbedtls.c",
]
# LWIPAPPFILES: All LWIP APPs
LWIPAPPFILES =
SNMPFILES + HTTPFILES + LWIPERFFILES + SMTPFILES + SNTPFILES + MDNSFILES +
NETBIOSNSFILES + TFTPFILES + MQTTFILES + MBEDTLS_FILES
\ No newline at end of file
LWIPDIR = "//third_party/lwip/src"
LWIP_INCLUDE_DIRS = [ "$LWIPDIR/include" ]
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES = [
"$LWIPDIR/core/init.c",
"$LWIPDIR/core/def.c",
"$LWIPDIR/core/dns.c",
"$LWIPDIR/core/inet_chksum.c",
"$LWIPDIR/core/ip.c",
"$LWIPDIR/core/mem.c",
"$LWIPDIR/core/memp.c",
"$LWIPDIR/core/netif.c",
"$LWIPDIR/core/pbuf.c",
"$LWIPDIR/core/raw.c",
"$LWIPDIR/core/stats.c",
"$LWIPDIR/core/sys.c",
"$LWIPDIR/core/altcp.c",
"$LWIPDIR/core/altcp_alloc.c",
"$LWIPDIR/core/altcp_tcp.c",
"$LWIPDIR/core/tcp.c",
"$LWIPDIR/core/tcp_in.c",
"$LWIPDIR/core/tcp_out.c",
"$LWIPDIR/core/timeouts.c",
"$LWIPDIR/core/udp.c",
]
CORE4FILES = [
"$LWIPDIR/core/ipv4/autoip.c",
"$LWIPDIR/core/ipv4/dhcp.c",
"$LWIPDIR/core/ipv4/etharp.c",
"$LWIPDIR/core/ipv4/icmp.c",
"$LWIPDIR/core/ipv4/igmp.c",
"$LWIPDIR/core/ipv4/ip4_frag.c",
"$LWIPDIR/core/ipv4/ip4.c",
"$LWIPDIR/core/ipv4/ip4_addr.c",
]
CORE6FILES = [
"$LWIPDIR/core/ipv6/dhcp6.c",
"$LWIPDIR/core/ipv6/ethip6.c",
"$LWIPDIR/core/ipv6/icmp6.c",
"$LWIPDIR/core/ipv6/inet6.c",
"$LWIPDIR/core/ipv6/ip6.c",
"$LWIPDIR/core/ipv6/ip6_addr.c",
"$LWIPDIR/core/ipv6/ip6_frag.c",
"$LWIPDIR/core/ipv6/mld6.c",
"$LWIPDIR/core/ipv6/nd6.c",
]
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES = [
"$LWIPDIR/api/api_lib.c",
"$LWIPDIR/api/api_msg.c",
"$LWIPDIR/api/err.c",
"$LWIPDIR/api/if_api.c",
"$LWIPDIR/api/netbuf.c",
"$LWIPDIR/api/netdb.c",
"$LWIPDIR/api/netifapi.c",
"$LWIPDIR/api/sockets.c",
"$LWIPDIR/api/tcpip.c",
]
# NETIFFILES: Files implementing various generic network interface functions
NETIFFILES = [
"$LWIPDIR/netif/ethernet.c",
"$LWIPDIR/netif/bridgeif.c",
"$LWIPDIR/netif/bridgeif_fdb.c",
"$LWIPDIR/netif/slipif.c",
]
# SIXLOWPAN: 6LoWPAN
SIXLOWPAN = [
"$LWIPDIR/netif/lowpan6_common.c",
"$LWIPDIR/netif/lowpan6.c",
"$LWIPDIR/netif/lowpan6_ble.c",
"$LWIPDIR/netif/zepif.c",
]
# PPPFILES: PPP
PPPFILES = [
"$LWIPDIR/netif/ppp/auth.c",
"$LWIPDIR/netif/ppp/ccp.c",
"$LWIPDIR/netif/ppp/chap-md5.c",
"$LWIPDIR/netif/ppp/chap_ms.c",
"$LWIPDIR/netif/ppp/chap-new.c",
"$LWIPDIR/netif/ppp/demand.c",
"$LWIPDIR/netif/ppp/eap.c",
"$LWIPDIR/netif/ppp/ecp.c",
"$LWIPDIR/netif/ppp/eui64.c",
"$LWIPDIR/netif/ppp/fsm.c",
"$LWIPDIR/netif/ppp/ipcp.c",
"$LWIPDIR/netif/ppp/ipv6cp.c",
"$LWIPDIR/netif/ppp/lcp.c",
"$LWIPDIR/netif/ppp/magic.c",
"$LWIPDIR/netif/ppp/mppe.c",
"$LWIPDIR/netif/ppp/multilink.c",
"$LWIPDIR/netif/ppp/ppp.c",
"$LWIPDIR/netif/ppp/pppapi.c",
"$LWIPDIR/netif/ppp/pppcrypt.c",
"$LWIPDIR/netif/ppp/pppoe.c",
"$LWIPDIR/netif/ppp/pppol2tp.c",
"$LWIPDIR/netif/ppp/pppos.c",
"$LWIPDIR/netif/ppp/upap.c",
"$LWIPDIR/netif/ppp/utils.c",
"$LWIPDIR/netif/ppp/vj.c",
"$LWIPDIR/netif/ppp/polarssl/arc4.c",
"$LWIPDIR/netif/ppp/polarssl/des.c",
"$LWIPDIR/netif/ppp/polarssl/md4.c",
"$LWIPDIR/netif/ppp/polarssl/md5.c",
"$LWIPDIR/netif/ppp/polarssl/sha1.c",
]
# LWIPNOAPPSFILES: All LWIP files without apps
LWIPNOAPPSFILES = COREFILES + CORE4FILES + CORE6FILES + APIFILES + NETIFFILES +
PPPFILES + SIXLOWPAN
# SNMPFILES: SNMPv2c agent
SNMPFILES = [
"$LWIPDIR/apps/snmp/snmp_asn1.c",
"$LWIPDIR/apps/snmp/snmp_core.c",
"$LWIPDIR/apps/snmp/snmp_mib2.c",
"$LWIPDIR/apps/snmp/snmp_mib2_icmp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_interfaces.c",
"$LWIPDIR/apps/snmp/snmp_mib2_ip.c",
"$LWIPDIR/apps/snmp/snmp_mib2_snmp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_system.c",
"$LWIPDIR/apps/snmp/snmp_mib2_tcp.c",
"$LWIPDIR/apps/snmp/snmp_mib2_udp.c",
"$LWIPDIR/apps/snmp/snmp_snmpv2_framework.c",
"$LWIPDIR/apps/snmp/snmp_snmpv2_usm.c",
"$LWIPDIR/apps/snmp/snmp_msg.c",
"$LWIPDIR/apps/snmp/snmpv3.c",
"$LWIPDIR/apps/snmp/snmp_netconn.c",
"$LWIPDIR/apps/snmp/snmp_pbuf_stream.c",
"$LWIPDIR/apps/snmp/snmp_raw.c",
"$LWIPDIR/apps/snmp/snmp_scalar.c",
"$LWIPDIR/apps/snmp/snmp_table.c",
"$LWIPDIR/apps/snmp/snmp_threadsync.c",
"$LWIPDIR/apps/snmp/snmp_traps.c",
]
# HTTPFILES: HTTP server + client
HTTPFILES = [
"$LWIPDIR/apps/http/altcp_proxyconnect.c",
"$LWIPDIR/apps/http/fs.c",
"$LWIPDIR/apps/http/http_client.c",
"$LWIPDIR/apps/http/httpd.c",
]
# MAKEFSDATA: MAKEFSDATA HTTP server host utility
MAKEFSDATAFILES = [ "$LWIPDIR/apps/http/makefsdata/makefsdata.c" ]
# LWIPERFFILES: IPERF server
LWIPERFFILES = [ "$LWIPDIR/apps/lwiperf/lwiperf.c" ]
# SMTPFILES: SMTP client
SMTPFILES = [ "$LWIPDIR/apps/smtp/smtp.c" ]
# SNTPFILES: SNTP client
SNTPFILES = [ "$LWIPDIR/apps/sntp/sntp.c" ]
# MDNSFILES: MDNS responder
MDNSFILES = [ "$LWIPDIR/apps/mdns/mdns.c" ]
# NETBIOSNSFILES: NetBIOS name server
NETBIOSNSFILES = [ "$LWIPDIR/apps/netbiosns/netbiosns.c" ]
# TFTPFILES: TFTP server files
TFTPFILES = [ "$LWIPDIR/apps/tftp/tftp_server.c" ]
# MQTTFILES: MQTT client files
MQTTFILES = [ "$LWIPDIR/apps/mqtt/mqtt.c" ]
# MBEDTLS_FILES: MBEDTLS related files of lwIP rep
MBEDTLS_FILES = [
"$LWIPDIR/apps/altcp_tls/altcp_tls_mbedtls.c",
"$LWIPDIR/apps/altcp_tls/altcp_tls_mbedtls_mem.c",
"$LWIPDIR/apps/snmp/snmpv3_mbedtls.c",
]
# LWIPAPPFILES: All LWIP APPs
LWIPAPPFILES =
SNMPFILES + HTTPFILES + LWIPERFFILES + SMTPFILES + SNTPFILES + MDNSFILES +
NETBIOSNSFILES + TFTPFILES + MQTTFILES + MBEDTLS_FILES
52 comment=6ca936f6b588cee702c638eee75c2436e6cf75de
......@@ -10,7 +10,7 @@
set(LWIP_VERSION_MAJOR "2")
set(LWIP_VERSION_MINOR "1")
set(LWIP_VERSION_REVISION "2")
set(LWIP_VERSION_REVISION "3")
# LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases
# LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions
# Numbers 1..31 are reserved for release candidates
......
......@@ -201,16 +201,16 @@ netconn_prepare_delete(struct netconn *conn)
API_MSG_VAR_ALLOC(msg);
API_MSG_VAR_REF(msg).conn = conn;
#if LWIP_TCP
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
/* get the time we started, which is later compared to
sys_now() + conn->send_timeout */
API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
#if LWIP_TCP
API_MSG_VAR_REF(msg).msg.sd.polls_left =
((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
#endif /* LWIP_TCP */
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
#endif /* LWIP_TCP */
err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg));
API_MSG_VAR_FREE(msg);
......@@ -500,7 +500,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
NETCONN_MBOX_WAITING_INC(conn);
if (netconn_is_nonblocking(conn)) {
if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_ARCH_TIMEOUT) {
if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_MBOX_EMPTY) {
API_MSG_VAR_FREE_ACCEPT(msg);
NETCONN_MBOX_WAITING_DEC(conn);
return ERR_WOULDBLOCK;
......@@ -597,7 +597,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf, u8_t apiflags)
NETCONN_MBOX_WAITING_INC(conn);
if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) ||
(conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) {
if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_ARCH_TIMEOUT) {
if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_MBOX_EMPTY) {
err_t err;
NETCONN_MBOX_WAITING_DEC(conn);
err = netconn_err(conn);
......@@ -1346,7 +1346,7 @@ void
netconn_thread_init(void)
{
sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
if ((sem == NULL) || !sys_sem_valid(sem)) {
if (!sys_sem_valid(sem)) {
/* call alloc only once */
LWIP_NETCONN_THREAD_SEM_ALLOC();
LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
......@@ -1357,7 +1357,7 @@ void
netconn_thread_cleanup(void)
{
sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
if ((sem != NULL) && sys_sem_valid(sem)) {
if (sys_sem_valid(sem)) {
/* call free only once */
LWIP_NETCONN_THREAD_SEM_FREE();
}
......
......@@ -128,8 +128,7 @@ lwip_gethostbyname(const char *name)
if (s_hostent.h_addr_list != NULL) {
u8_t idx;
for (idx = 0; s_hostent.h_addr_list[idx]; idx++) {
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t *)s_hostent.h_addr_list[idx])));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa(s_phostent_addr[idx])));
}
}
#endif /* DNS_DEBUG */
......@@ -306,7 +305,11 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
/* service name specified: convert to port number
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
port_nr = atoi(servname);
if ((port_nr <= 0) || (port_nr > 0xffff)) {
if (port_nr == 0 && (servname[0] != '0')) {
/* atoi failed - service was not numeric */
return EAI_SERVICE;
}
if ((port_nr < 0) || (port_nr > 0xffff)) {
return EAI_SERVICE;
}
}
......
......@@ -693,7 +693,6 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
err = netconn_peer(newconn, &naddr, &port);
if (err != ERR_OK) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
netconn_delete(newconn);
free_socket(nsock, 1);
sock_set_errno(sock, err_to_errno(err));
done_socket(sock);
......@@ -2140,7 +2139,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* Call lwip_selscan again: there could have been events between
the last scan (without us on the list) and putting us on the list! */
nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
if (!nready) {
if (nready < 0) {
set_errno(EBADF);
} else if (!nready) {
/* Still none ready, just wait to be woken */
if (timeout == 0) {
/* Wait forever */
......@@ -2169,7 +2170,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
(exceptset && FD_ISSET(i, exceptset))) {
struct lwip_sock *sock;
SYS_ARCH_PROTECT(lev);
sock = tryget_socket_unconn_locked(i);
sock = tryget_socket_unconn_nouse(i);
LWIP_ASSERT("socket gone at the end of select", sock != NULL);
if (sock != NULL) {
/* for now, handle select_waiting==0... */
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
......@@ -2177,7 +2179,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
sock->select_waiting--;
}
SYS_ARCH_UNPROTECT(lev);
done_socket(sock);
} else {
SYS_ARCH_UNPROTECT(lev);
/* Not a valid socket */
......@@ -2214,6 +2215,11 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* See what's set now after waiting */
nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
if (nready < 0) {
set_errno(EBADF);
lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
return -1;
}
}
}
}
......
......@@ -217,7 +217,7 @@ tcpip_thread_poll_one(void)
int ret = 0;
struct tcpip_msg *msg;
if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_ARCH_TIMEOUT) {
if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_MBOX_EMPTY) {
LOCK_TCPIP_CORE();
if (msg != NULL) {
tcpip_thread_handle_msg(msg);
......
......@@ -40,10 +40,8 @@
* track of the ratio of application data and TLS overhead would be too much.
*
* Mandatory security-related configuration:
* - define ALTCP_MBEDTLS_RNG_FN to mbedtls_entropy_func to use the standard mbedTLS
* entropy and ensure to add at least one strong entropy source to your mbedtls port
* (implement mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong
* entropy)
* - ensure to add at least one strong entropy source to your mbedtls port (implement
* mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong entropy)
* - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing
* GOOD custom entropy
*
......@@ -78,6 +76,7 @@
#include "mbedtls/platform.h"
#include "mbedtls/memory_buffer_alloc.h"
#include "mbedtls/ssl_cache.h"
#include "mbedtls/ssl_ticket.h"
#include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */
......@@ -97,16 +96,29 @@ extern const struct altcp_functions altcp_mbedtls_functions;
/** Our global mbedTLS configuration (server-specific, not connection-specific) */
struct altcp_tls_config {
mbedtls_ssl_config conf;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_x509_crt *cert;
mbedtls_pk_context *pkey;
uint8_t cert_count;
uint8_t cert_max;
uint8_t pkey_count;
uint8_t pkey_max;
mbedtls_x509_crt *ca;
#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE
/** Inter-connection cache for fast connection startup */
struct mbedtls_ssl_cache_context cache;
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS
mbedtls_ssl_ticket_context ticket_ctx;
#endif
};
/** Entropy and random generator are shared by all mbedTLS configuration */
struct altcp_tls_entropy_rng {
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
int ref;
};
static struct altcp_tls_entropy_rng *altcp_tls_entropy_rng;
static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err);
static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn);
......@@ -449,6 +461,7 @@ altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len)
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
}
state = (altcp_mbedtls_state_t *)conn->state;
LWIP_ASSERT("state != NULL", state != NULL);
p = state->rx;
/* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */
......@@ -636,41 +649,26 @@ altcp_tls_context(struct altcp_pcb *conn)
return NULL;
}
#if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF
#if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF
static void
altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
{
LWIP_UNUSED_ARG(ctx);
LWIP_UNUSED_ARG(level);
LWIP_UNUSED_ARG(file);
LWIP_UNUSED_ARG(line);
LWIP_UNUSED_ARG(str);
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("%s:%04d: %s", file, line, str));
}
#endif
#ifndef ALTCP_MBEDTLS_RNG_FN
/** ATTENTION: It is *really* important to *NOT* use this dummy RNG in production code!!!! */
static int
dummy_rng(void *ctx, unsigned char *buffer, size_t len)
{
static size_t ctr;
size_t i;
LWIP_UNUSED_ARG(ctx);
for (i = 0; i < len; i++) {
buffer[i] = (unsigned char)++ctr;
if (level >= ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN) {
LWIP_DEBUGF(ALTCP_MBEDTLS_LIB_DEBUG, ("%s:%04d: %s", file, line, str));
}
return 0;
}
#define ALTCP_MBEDTLS_RNG_FN dummy_rng
#endif /* ALTCP_MBEDTLS_RNG_FN */
#endif
/** Create new TLS configuration
* ATTENTION: Server certificate and private key have to be added outside this function!
*/
static struct altcp_tls_config *
altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca)
altcp_tls_create_config(int is_server, uint8_t cert_count, uint8_t pkey_count, int have_ca)
{
size_t sz;
int ret;
......@@ -679,49 +677,68 @@ altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca
if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS,
("altcp_tls: TCP_WND is smaller than the RX decryption buffer, connection RX might stall!\n"));
("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n"));
}
altcp_mbedtls_mem_init();
sz = sizeof(struct altcp_tls_config);
if (have_cert) {
sz += sizeof(mbedtls_x509_crt);
if (cert_count > 0) {
sz += (cert_count * sizeof(mbedtls_x509_crt));
}
if (have_ca) {
sz += sizeof(mbedtls_x509_crt);
}
if (have_pkey) {
sz += sizeof(mbedtls_pk_context);
if (pkey_count > 0) {
sz += (pkey_count * sizeof(mbedtls_pk_context));
}
conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz);
if (conf == NULL) {
return NULL;
}
conf->cert_max = cert_count;
mem = (mbedtls_x509_crt *)(conf + 1);
if (have_cert) {
if (cert_count > 0) {
conf->cert = mem;
mem++;
mem += cert_count;
}
if (have_ca) {
conf->ca = mem;
mem++;
}
if (have_pkey) {
conf->pkey_max = pkey_count;
if (pkey_count > 0) {
conf->pkey = (mbedtls_pk_context *)mem;
}
mbedtls_ssl_config_init(&conf->conf);
mbedtls_entropy_init(&conf->entropy);
mbedtls_ctr_drbg_init(&conf->ctr_drbg);
/* Seed the RNG */
ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret));
altcp_mbedtls_free_config(conf);
return NULL;
if (!altcp_tls_entropy_rng) {
altcp_tls_entropy_rng = (struct altcp_tls_entropy_rng *)altcp_mbedtls_alloc_config(sizeof(struct altcp_tls_entropy_rng));
if (altcp_tls_entropy_rng) {
altcp_tls_entropy_rng->ref = 1;
mbedtls_entropy_init(&altcp_tls_entropy_rng->entropy);
mbedtls_ctr_drbg_init(&altcp_tls_entropy_rng->ctr_drbg);
/* Seed the RNG, only once */
ret = mbedtls_ctr_drbg_seed(&altcp_tls_entropy_rng->ctr_drbg,
mbedtls_entropy_func, &altcp_tls_entropy_rng->entropy,
ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret));
mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
altcp_mbedtls_free_config(altcp_tls_entropy_rng);
altcp_tls_entropy_rng = NULL;
altcp_mbedtls_free_config(conf);
return NULL;
}
} else {
altcp_mbedtls_free_config(conf);
return NULL;
}
} else {
altcp_tls_entropy_rng->ref++;
}
/* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */
......@@ -729,72 +746,125 @@ altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret));
if (altcp_tls_entropy_rng->ref == 1) {
mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
altcp_mbedtls_free_config(altcp_tls_entropy_rng);
altcp_tls_entropy_rng = NULL;
}
altcp_mbedtls_free_config(conf);
return NULL;
}
mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg);
#if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF
mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg);
#if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF
mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout);
#endif
#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE
mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
mbedtls_ssl_cache_set_timeout(&conf->cache, 30);
mbedtls_ssl_cache_set_max_entries(&conf->cache, 30);
mbedtls_ssl_cache_set_timeout(&conf->cache, ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS);
mbedtls_ssl_cache_set_max_entries(&conf->cache, ALTCP_MBEDTLS_SESSION_CACHE_SIZE);
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS
mbedtls_ssl_ticket_init(&conf->ticket_ctx);
ret = mbedtls_ssl_ticket_setup(&conf->ticket_ctx, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg,
ALTCP_MBEDTLS_SESSION_TICKET_CIPHER, ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS);
if (ret) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_ticket_setup failed: %d\n", ret));
altcp_mbedtls_free_config(conf);
return NULL;
}
mbedtls_ssl_conf_session_tickets_cb(&conf->conf, mbedtls_ssl_ticket_write, mbedtls_ssl_ticket_parse,
&conf->ticket_ctx);
#endif
return conf;
}
/** Create new TLS configuration
* This is a suboptimal version that gets the encrypted private key and its password,
* as well as the server certificate.
*/
struct altcp_tls_config *
altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len)
struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count)
{
struct altcp_tls_config *conf = altcp_tls_create_config(1, cert_count, cert_count, 0);
if (conf == NULL) {
return NULL;
}
mbedtls_ssl_conf_ca_chain(&conf->conf, NULL, NULL);
return conf;
}
err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config,
const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len)
{
int ret;
mbedtls_x509_crt *srvcert;
mbedtls_pk_context *pkey;
struct altcp_tls_config *conf = altcp_tls_create_config(1, 1, 1, 0);
if (conf == NULL) {
return NULL;
if (config->cert_count >= config->cert_max) {
return ERR_MEM;
}
if (config->pkey_count >= config->pkey_max) {
return ERR_MEM;
}
srvcert = conf->cert;
srvcert = config->cert + config->cert_count;
mbedtls_x509_crt_init(srvcert);
pkey = conf->pkey;
pkey = config->pkey + config->pkey_count;
mbedtls_pk_init(pkey);
/* Load the certificates and private key */
ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret));
altcp_mbedtls_free_config(conf);
return NULL;
return ERR_VAL;
}
ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret));
mbedtls_x509_crt_free(srvcert);
altcp_mbedtls_free_config(conf);
return NULL;
return ERR_VAL;
}
mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert->next, NULL);
ret = mbedtls_ssl_conf_own_cert(&conf->conf, srvcert, pkey);
ret = mbedtls_ssl_conf_own_cert(&config->conf, srvcert, pkey);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret));
mbedtls_x509_crt_free(srvcert);
mbedtls_pk_free(pkey);
return ERR_VAL;
}
config->cert_count++;
config->pkey_count++;
return ERR_OK;
}
/** Create new TLS configuration
* This is a suboptimal version that gets the encrypted private key and its password,
* as well as the server certificate.
*/
struct altcp_tls_config *
altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len)
{
struct altcp_tls_config *conf = altcp_tls_create_config_server(1);
if (conf == NULL) {
return NULL;
}
if (altcp_tls_config_server_add_privkey_cert(conf, privkey, privkey_len,
privkey_pass, privkey_pass_len, cert, cert_len) != ERR_OK) {
altcp_mbedtls_free_config(conf);
return NULL;
}
return conf;
}
......@@ -802,7 +872,7 @@ static struct altcp_tls_config *
altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth)
{
int ret;
struct altcp_tls_config *conf = altcp_tls_create_config(0, is_2wayauth, is_2wayauth, ca != NULL);
struct altcp_tls_config *conf = altcp_tls_create_config(0, (is_2wayauth) ? 1 : 0, (is_2wayauth) ? 1 : 0, ca != NULL);
if (conf == NULL) {
return NULL;
}
......@@ -886,8 +956,21 @@ altcp_tls_free_config(struct altcp_tls_config *conf)
}
if (conf->ca) {
mbedtls_x509_crt_free(conf->ca);
}
}
altcp_mbedtls_free_config(conf);
if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref)
altcp_tls_entropy_rng->ref--;
}
void
altcp_tls_free_entropy(void)
{
if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref == 0) {
mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
altcp_mbedtls_free_config(altcp_tls_entropy_rng);
altcp_tls_entropy_rng = NULL;
}
}
/* "virtual" functions */
......@@ -944,6 +1027,11 @@ altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
}
lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err);
if (lpcb != NULL) {
altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
/* Free members of the ssl context (not used on listening pcb). This
includes freeing input/output buffers, so saves ~32KByte by default */
mbedtls_ssl_free(&state->ssl_context);
conn->inner_conn = lpcb;
altcp_accept(lpcb, altcp_mbedtls_lower_accept);
return conn;
......@@ -1169,6 +1257,10 @@ const struct altcp_functions altcp_mbedtls_functions = {
altcp_default_get_tcp_addrinfo,
altcp_default_get_ip,
altcp_default_get_port
#if LWIP_TCP_KEEPALIVE
, altcp_default_keepalive_disable
, altcp_default_keepalive_enable
#endif
#ifdef LWIP_DEBUG
, altcp_default_dbg_get_tcp_state
#endif
......
......@@ -1301,6 +1301,22 @@ http_send_data_ssi(struct altcp_pcb *pcb, struct http_state *hs)
ssi->tag_state = TAG_NONE;
}
#if LWIP_HTTPD_DYNAMIC_FILE_READ && !LWIP_HTTPD_SSI_INCLUDE_TAG
if ((ssi->tag_state == TAG_NONE) &&
(ssi->parsed - hs->file < ssi->tag_index)) {
for(u16_t i = 0;i < ssi->tag_index;i++) {
ssi->tag_insert[i] = http_ssi_tag_desc[ssi->tag_type].lead_in[i];
}
ssi->tag_insert_len = ssi->tag_index;
hs->file += ssi->parsed - hs->file;
hs->left -= ssi->parsed - hs->file;
ssi->tag_end = hs->file;
ssi->tag_index = 0;
ssi->tag_state = TAG_SENDING;
break;
}
#endif
/* Move on to the next character in the buffer */
ssi->parse_left--;
ssi->parsed++;
......
......@@ -664,25 +664,24 @@ mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result)
/**
* Complete MQTT message received or buffer full
* @param client MQTT client
* @param fixed_hdr_idx header index
* @param fixed_hdr_len length of fixed header
* @param length length received part
* @param remaining_length Remaining length of complete message
*/
static mqtt_connection_status_t
mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length)
mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_len, u16_t length, u32_t remaining_length)
{
mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED;
u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx;
size_t var_hdr_payload_bufsize = sizeof(client->rx_buffer) - fixed_hdr_idx;
u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_len;
size_t var_hdr_payload_bufsize = sizeof(client->rx_buffer) - fixed_hdr_len;
/* Control packet type */
u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]);
u16_t pkt_id = 0;
LWIP_ASSERT("client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN", client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN);
LWIP_ASSERT("fixed_hdr_idx <= client->msg_idx", fixed_hdr_idx <= client->msg_idx);
LWIP_ERROR("buffer length mismatch", fixed_hdr_idx + length <= MQTT_VAR_HEADER_BUFFER_LEN,
LWIP_ASSERT("fixed_hdr_len <= client->msg_idx", fixed_hdr_len <= client->msg_idx);
LWIP_ERROR("buffer length mismatch", fixed_hdr_len + length <= MQTT_VAR_HEADER_BUFFER_LEN,
return MQTT_CONNECT_DISCONNECTED);
if (pkt_type == MQTT_MSG_TYPE_CONNACK) {
......@@ -773,7 +772,9 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u
LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short packet (payload)\n"));
goto out_disconnect;
}
client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0);
if (client->data_cb != NULL) {
client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0);
}
/* Reply if QoS > 0 */
if (remaining_length == 0 && qos > 0) {
/* Send PUBACK for QoS 1 or PUBREC for QoS 2 */
......@@ -840,61 +841,59 @@ mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p)
{
u16_t in_offset = 0;
u32_t msg_rem_len = 0;
u8_t fixed_hdr_idx = 0;
u8_t fixed_hdr_len = 0;
u8_t b = 0;
while (p->tot_len > in_offset) {
/* We ALWAYS parse the header here first. Even if the header was not
included in this segment, we re-parse it here by buffering it in
client->rx_buffer. client->msg_idx keeps track of this. */
if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) {
if ((fixed_hdr_len < 2) || ((b & 0x80) != 0)) {
if (fixed_hdr_idx < client->msg_idx) {
if (fixed_hdr_len < client->msg_idx) {
/* parse header from old pbuf (buffered in client->rx_buffer) */
b = client->rx_buffer[fixed_hdr_idx];
b = client->rx_buffer[fixed_hdr_len];
} else {
/* parse header from this pbuf and save it in client->rx_buffer in case
it comes in segmented */
b = pbuf_get_at(p, in_offset++);
client->rx_buffer[client->msg_idx++] = b;
}
fixed_hdr_idx++;
fixed_hdr_len++;
if (fixed_hdr_idx >= 2) {
if (fixed_hdr_len >= 2) {
/* fixed header contains at least 2 bytes but can contain more, depending on
'remaining length'. All bytes but the last of this have 0x80 set to
indicate more bytes are coming. */
msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7);
msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_len - 2) * 7);
if ((b & 0x80) == 0) {
/* fixed header is done */
LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: Remaining length after fixed header: %"U32_F"\n", msg_rem_len));
if (msg_rem_len == 0) {
/* Complete message with no extra headers of payload received */
mqtt_message_received(client, fixed_hdr_idx, 0, 0);
mqtt_message_received(client, fixed_hdr_len, 0, 0);
client->msg_idx = 0;
fixed_hdr_idx = 0;
fixed_hdr_len = 0;
} else {
/* Bytes remaining in message (changes remaining length if this is
not the first segment of this message) */
msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx;
msg_rem_len = (msg_rem_len + fixed_hdr_len) - client->msg_idx;
}
}
}
} else {
/* Fixed header has been parsed, parse variable header */
u16_t cpy_len, cpy_start, buffer_space;
cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx;
u16_t cpy_len, buffer_space;
/* Allow to copy the lesser one of available length in input data or bytes remaining in message */
cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len);
/* Limit to available space in buffer */
buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start;
buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_len;
if (cpy_len > buffer_space) {
cpy_len = buffer_space;
}
pbuf_copy_partial(p, client->rx_buffer + cpy_start, cpy_len, in_offset);
pbuf_copy_partial(p, client->rx_buffer + fixed_hdr_len, cpy_len, in_offset);
/* Advance get and put indexes */
client->msg_idx += cpy_len;
......@@ -904,7 +903,7 @@ mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p)
LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: msg_idx: %"U32_F", cpy_len: %"U16_F", remaining %"U32_F"\n", client->msg_idx, cpy_len, msg_rem_len));
if ((msg_rem_len == 0) || (cpy_len == buffer_space)) {
/* Whole message received or buffer is full */
mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len);
mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_len, cpy_len, msg_rem_len);
if (res != MQTT_CONNECT_ACCEPTED) {
return res;
}
......@@ -912,7 +911,7 @@ mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p)
/* Reset parser state */
client->msg_idx = 0;
/* msg_tot_len = 0; */
fixed_hdr_idx = 0;
fixed_hdr_len = 0;
}
}
}
......
......@@ -240,12 +240,12 @@ static struct udp_pcb *netbiosns_pcb;
/** Decode a NetBIOS name (from packet to string) */
static int
netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
netbiosns_name_decode(const char *name_enc, char *name_dec, int name_dec_len)
{
char *pname;
char cname;
char cnbname;
int idx = 0;
const char *pname;
char cname;
char cnbname;
int idx = 0;
LWIP_UNUSED_ARG(name_dec_len);
......
......@@ -238,9 +238,9 @@ struct sntp_server {
};
static struct sntp_server sntp_servers[SNTP_MAX_SERVERS];
#if SNTP_GET_SERVERS_FROM_DHCP
#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
static u8_t sntp_set_servers_from_dhcp;
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
#if SNTP_SUPPORT_MULTIPLE_SERVERS
/** The currently used server (initialized to 0) */
static u8_t sntp_current_server;
......@@ -371,6 +371,7 @@ sntp_retry(void *arg)
sntp_retry_timeout));
/* set up a timer to send a retry and increase the retry delay */
sys_untimeout(sntp_request, NULL);
sys_timeout(sntp_retry_timeout, sntp_request, NULL);
#if SNTP_RETRY_TIMEOUT_EXP
......@@ -382,6 +383,8 @@ sntp_retry(void *arg)
if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
(new_retry_timeout > sntp_retry_timeout)) {
sntp_retry_timeout = new_retry_timeout;
} else {
sntp_retry_timeout = SNTP_RETRY_TIMEOUT_MAX;
}
}
#endif /* SNTP_RETRY_TIMEOUT_EXP */
......@@ -558,6 +561,7 @@ sntp_send_request(const ip_addr_t *server_addr)
sntp_servers[sntp_current_server].reachability <<= 1;
#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
/* set up receive timeout: try next server or retry on timeout */
sys_untimeout(sntp_try_next_server, NULL);
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
#if SNTP_CHECK_RESPONSE >= 1
/* save server address to verify it in sntp_recv */
......@@ -567,6 +571,7 @@ sntp_send_request(const ip_addr_t *server_addr)
LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
(u32_t)SNTP_RETRY_TIMEOUT));
/* out of memory: set up a timer to send a retry */
sys_untimeout(sntp_request, NULL);
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
}
}
......@@ -635,6 +640,7 @@ sntp_request(void *arg)
} else {
/* address conversion failed, try another server */
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
sys_untimeout(sntp_try_next_server, NULL);
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
}
}
......@@ -648,6 +654,7 @@ void
sntp_init(void)
{
/* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_init: SNTP initialised\n"));
#ifdef SNTP_SERVER_ADDRESS
#if SNTP_SERVER_DNS
......@@ -750,7 +757,7 @@ sntp_getreachability(u8_t idx)
}
#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
#if SNTP_GET_SERVERS_FROM_DHCP
#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
/**
* Config SNTP server handling by IP address, name, or DHCP; clear table
* @param set_servers_from_dhcp enable or disable getting server addresses from dhcp
......@@ -764,7 +771,7 @@ sntp_servermode_dhcp(int set_servers_from_dhcp)
sntp_set_servers_from_dhcp = new_mode;
}
}
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
/**
* @ingroup sntp
......@@ -816,6 +823,33 @@ dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server)
}
#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
#if LWIP_IPV6_DHCP6 && SNTP_GET_SERVERS_FROM_DHCPV6
/**
* Initialize one of the NTP servers by IP address, required by DHCPV6
*
* @param num the number of NTP server addresses to set must be < SNTP_MAX_SERVERS
* @param server array of IP address of the NTP servers to set
*/
void
dhcp6_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs)
{
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u NTP server(s) via DHCPv6\n",
(sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
num_ntp_servers));
if (sntp_set_servers_from_dhcp && num_ntp_servers) {
u8_t i;
for (i = 0; (i < num_ntp_servers) && (i < SNTP_MAX_SERVERS); i++) {
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: NTP server %u: %s\n",
i, ipaddr_ntoa(&ntp_server_addrs[i])));
sntp_setserver(i, &ntp_server_addrs[i]);
}
for (i = num_ntp_servers; i < SNTP_MAX_SERVERS; i++) {
sntp_setserver(i, NULL);
}
}
}
#endif /* LWIP_DHCPv6 && SNTP_GET_SERVERS_FROM_DHCPV6 */
/**
* @ingroup sntp
* Obtain one of the currently configured by IP address (or DHCP) NTP servers
......
......@@ -501,6 +501,24 @@ altcp_get_port(struct altcp_pcb *conn, int local)
return 0;
}
#if LWIP_TCP_KEEPALIVE
void
altcp_keepalive_disable(struct altcp_pcb *conn)
{
if (conn && conn->fns && conn->fns->keepalive_disable) {
conn->fns->keepalive_disable(conn);
}
}
void
altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
{
if (conn && conn->fns && conn->fns->keepalive_enable) {
conn->fns->keepalive_enable(conn, idle, intvl, count);
}
}
#endif
#ifdef LWIP_DEBUG
enum tcp_state
altcp_dbg_get_tcp_state(struct altcp_pcb *conn)
......@@ -666,6 +684,24 @@ altcp_default_get_port(struct altcp_pcb *conn, int local)
return 0;
}
#if LWIP_TCP_KEEPALIVE
void
altcp_default_keepalive_disable(struct altcp_pcb *conn)
{
if (conn && conn->inner_conn) {
altcp_keepalive_disable(conn->inner_conn);
}
}
void
altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
{
if (conn && conn->inner_conn) {
altcp_keepalive_enable(conn->inner_conn, idle, intvl, count);
}
}
#endif
#ifdef LWIP_DEBUG
enum tcp_state
altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn)
......
......@@ -49,6 +49,7 @@
#include "lwip/altcp_tcp.h"
#include "lwip/priv/altcp_priv.h"
#include "lwip/tcp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/mem.h"
#include <string.h>
......@@ -160,21 +161,25 @@ static void
altcp_tcp_remove_callbacks(struct tcp_pcb *tpcb)
{
tcp_arg(tpcb, NULL);
tcp_recv(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_poll(tpcb, NULL, tpcb->pollinterval);
if (tpcb->state != LISTEN) {
tcp_recv(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_poll(tpcb, NULL, tpcb->pollinterval);
}
}
static void
altcp_tcp_setup_callbacks(struct altcp_pcb *conn, struct tcp_pcb *tpcb)
{
tcp_arg(tpcb, conn);
tcp_recv(tpcb, altcp_tcp_recv);
tcp_sent(tpcb, altcp_tcp_sent);
tcp_err(tpcb, altcp_tcp_err);
/* tcp_poll is set when interval is set by application */
/* listen is set totally different :-) */
/* this might be called for LISTN when close fails... */
if (tpcb->state != LISTEN) {
tcp_recv(tpcb, altcp_tcp_recv);
tcp_sent(tpcb, altcp_tcp_sent);
tcp_err(tpcb, altcp_tcp_err);
/* tcp_poll is set when interval is set by application */
}
}
static void
......@@ -446,6 +451,31 @@ altcp_tcp_setprio(struct altcp_pcb *conn, u8_t prio)
}
}
#if LWIP_TCP_KEEPALIVE
static void
altcp_tcp_keepalive_disable(struct altcp_pcb *conn)
{
if (conn && conn->state) {
struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
ALTCP_TCP_ASSERT_CONN(conn);
ip_reset_option(pcb, SOF_KEEPALIVE);
}
}
static void
altcp_tcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t cnt)
{
if (conn && conn->state) {
struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
ALTCP_TCP_ASSERT_CONN(conn);
ip_set_option(pcb, SOF_KEEPALIVE);
pcb->keep_idle = idle ? idle : TCP_KEEPIDLE_DEFAULT;
pcb->keep_intvl = intvl ? intvl : TCP_KEEPINTVL_DEFAULT;
pcb->keep_cnt = cnt ? cnt : TCP_KEEPCNT_DEFAULT;
}
}
#endif
static void
altcp_tcp_dealloc(struct altcp_pcb *conn)
{
......@@ -535,6 +565,10 @@ const struct altcp_functions altcp_tcp_functions = {
altcp_tcp_get_tcp_addrinfo,
altcp_tcp_get_ip,
altcp_tcp_get_port
#if LWIP_TCP_KEEPALIVE
, altcp_tcp_keepalive_disable
, altcp_tcp_keepalive_enable
#endif
#ifdef LWIP_DEBUG
, altcp_tcp_dbg_get_tcp_state
#endif
......
......@@ -237,8 +237,9 @@ PACK_STRUCT_END
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
#endif
#endif /* LWIP_NETCONN && LWIP_TCP */
#if LWIP_SOCKET
#endif /* LWIP_SOCKET */
// #if LWIP_NETCONN_FULLDUPLEX && !LWIP_NETCONN_SEM_PER_THREAD
// #error "For LWIP_NETCONN_FULLDUPLEX to work, LWIP_NETCONN_SEM_PER_THREAD is required"
// #endif
/* Compile-time checks for deprecated options.
......
......@@ -160,6 +160,12 @@ u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
@todo: move this into struct dhcp? */
u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
#endif
#ifndef LWIP_DHCP_INPUT_ERROR
#define LWIP_DHCP_INPUT_ERROR(message, expression, handler) do { if (!(expression)) { \
handler;} } while(0)
#endif
static u8_t dhcp_discover_request_options[] = {
DHCP_OPTION_SUBNET_MASK,
DHCP_OPTION_ROUTER,
......@@ -1115,13 +1121,6 @@ dhcp_bind(struct netif *netif)
}
ip4_addr_copy(gw_addr, dhcp->offered_gw_addr);
/* gateway address not given? */
if (ip4_addr_isany_val(gw_addr)) {
/* copy network address */
ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
/* use first host address on network as gateway */
ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
}
#if LWIP_DHCP_AUTOIP_COOP
if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
......@@ -1349,6 +1348,7 @@ dhcp_release_and_stop(struct netif *netif)
/* create and initialize the DHCP message header */
struct pbuf *p_out;
u16_t options_out_len;
dhcp_set_state(dhcp, DHCP_STATE_OFF);
p_out = dhcp_create_msg(netif, dhcp, DHCP_RELEASE, &options_out_len);
if (p_out != NULL) {
struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
......@@ -1365,10 +1365,12 @@ dhcp_release_and_stop(struct netif *netif)
/* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
}
}
/* remove IP address from interface (prevents routing from selecting this interface) */
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
/* remove IP address from interface (prevents routing from selecting this interface) */
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
} else {
dhcp_set_state(dhcp, DHCP_STATE_OFF);
}
#if LWIP_DHCP_AUTOIP_COOP
if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
......@@ -1377,8 +1379,6 @@ dhcp_release_and_stop(struct netif *netif)
}
#endif /* LWIP_DHCP_AUTOIP_COOP */
dhcp_set_state(dhcp, DHCP_STATE_OFF);
if (dhcp->pcb_allocated != 0) {
dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
dhcp->pcb_allocated = 0;
......@@ -1509,6 +1509,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
u8_t *options;
u16_t offset;
u16_t offset_max;
u16_t options_offset;
u16_t options_idx;
u16_t options_idx_max;
struct pbuf *q;
......@@ -1541,6 +1542,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
options_idx_max = p->tot_len;
again:
q = p;
options_offset = options_idx;
while ((q != NULL) && (options_idx >= q->len)) {
options_idx = (u16_t)(options_idx - q->len);
options_idx_max = (u16_t)(options_idx_max - q->len);
......@@ -1579,58 +1581,58 @@ again:
/* will be increased below */
break;
case (DHCP_OPTION_SUBNET_MASK):
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
break;
case (DHCP_OPTION_ROUTER):
decode_len = 4; /* only copy the first given router */
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_ROUTER;
break;
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
case (DHCP_OPTION_DNS_SERVER):
/* special case: there might be more than one server */
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
/* limit number of DNS servers */
decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
break;
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
case (DHCP_OPTION_LEASE_TIME):
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
break;
#if LWIP_DHCP_GET_NTP_SRV
case (DHCP_OPTION_NTP):
/* special case: there might be more than one server */
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
LWIP_DHCP_INPUT_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;);
LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
break;
#endif /* LWIP_DHCP_GET_NTP_SRV*/
case (DHCP_OPTION_OVERLOAD):
LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
/* decode overload only in options, not in file/sname: invalid packet */
LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("overload in file/sname", options_offset == DHCP_OPTIONS_OFS, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_OVERLOAD;
break;
case (DHCP_OPTION_MESSAGE_TYPE):
LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
break;
case (DHCP_OPTION_SERVER_ID):
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_SERVER_ID;
break;
case (DHCP_OPTION_T1):
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_T1;
break;
case (DHCP_OPTION_T2):
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_T2;
break;
default:
......@@ -1662,7 +1664,7 @@ decode_next:
if (decode_len > 4) {
/* decode more than one u32_t */
u16_t next_val_offset;
LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
dhcp_got_option(dhcp, decode_idx);
dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
decode_len = (u8_t)(decode_len - 4);
......@@ -1677,7 +1679,7 @@ decode_next:
} else if (decode_len == 4) {
value = lwip_ntohl(value);
} else {
LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
value = ((u8_t *)&value)[0];
}
dhcp_got_option(dhcp, decode_idx);
......@@ -1690,7 +1692,7 @@ decode_next:
offset_max = (u16_t)(offset_max - q->len);
if (offset < offset_max) {
q = q->next;
LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
LWIP_DHCP_INPUT_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
options = (u8_t *)q->payload;
} else {
/* We've run out of bytes, probably no end marker. Don't proceed. */
......
......@@ -983,6 +983,14 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
/* We don't re-send arp request in etharp_tmr, but we still queue packets,
since this failure could be temporary, and the next packet calling
etharp_query again could lead to sending the queued packets. */
} else {
/* ARP request successfully sent */
if ((arp_table[i].state == ETHARP_STATE_PENDING) && !is_new_entry) {
/* A new ARP request has been sent for a pending entry. Reset the ctime to
not let it expire too fast. */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: reset ctime for entry %"S16_F"\n", (s16_t)i));
arp_table[i].ctime = 0;
}
}
if (q == NULL) {
return result;
......
......@@ -62,7 +62,7 @@
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
/* The amount of data from the original packet to return in a dest-unreachable */
/* The maximum amount of data from the original packet to return in a dest-unreachable */
#define ICMP_DEST_UNREACH_DATASIZE 8
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
......@@ -345,20 +345,26 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
struct icmp_echo_hdr *icmphdr;
ip4_addr_t iphdr_src;
struct netif *netif;
u16_t response_pkt_len;
/* increase number of messages attempted to send */
MIB2_STATS_INC(mib2.icmpoutmsgs);
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
PBUF_RAM);
/* Keep IP header + up to 8 bytes */
response_pkt_len = IP_HLEN + ICMP_DEST_UNREACH_DATASIZE;
if (p->tot_len < response_pkt_len) {
response_pkt_len = p->tot_len;
}
/* ICMP header + part of original packet */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + response_pkt_len, PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
MIB2_STATS_INC(mib2.icmpouterrors);
return;
}
LWIP_ASSERT("check that first pbuf can hold icmp message",
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
(q->len >= (sizeof(struct icmp_echo_hdr) + response_pkt_len)));
iphdr = (struct ip_hdr *)p->payload;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
......@@ -375,7 +381,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
/* copy fields from original packet */
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
response_pkt_len);
ip4_addr_copy(iphdr_src, iphdr->src);
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
......
......@@ -173,6 +173,8 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
}
for (;;) {
if (lwip_isdigit(c)) {
if((base == 8) && ((u32_t)(c - '0') >= 8))
break;
val = (val * base) + (u32_t)(c - '0');
c = *++cp;
} else if (base == 16 && lwip_isxdigit(c)) {
......
......@@ -451,7 +451,16 @@ dhcp6_msg_finalize(u16_t options_out_len, struct pbuf *p_out)
static void
dhcp6_information_request(struct netif *netif, struct dhcp6 *dhcp6)
{
const u16_t requested_options[] = {DHCP6_OPTION_DNS_SERVERS, DHCP6_OPTION_DOMAIN_LIST, DHCP6_OPTION_SNTP_SERVERS};
const u16_t requested_options[] = {
#if LWIP_DHCP6_PROVIDE_DNS_SERVERS
DHCP6_OPTION_DNS_SERVERS,
DHCP6_OPTION_DOMAIN_LIST
#endif
#if LWIP_DHCP6_GET_NTP_SRV
, DHCP6_OPTION_SNTP_SERVERS
#endif
};
u16_t msecs;
struct pbuf *p_out;
u16_t options_out_len;
......@@ -527,7 +536,7 @@ dhcp6_handle_config_reply(struct netif *netif, struct pbuf *p_msg_in)
u16_t idx;
u8_t n;
memset(&dns_addr, 0, sizeof(dns_addr));
ip_addr_set_zero_ip6(&dns_addr);
dns_addr6 = ip_2_ip6(&dns_addr);
for (n = 0, idx = op_start; (idx < op_start + op_len) && (n < LWIP_DHCP6_PROVIDE_DNS_SERVERS);
n++, idx += sizeof(struct ip6_addr_packed)) {
......
......@@ -57,9 +57,9 @@
#include <string.h>
#if LWIP_ICMP6_DATASIZE == 0
#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN))
#undef LWIP_ICMP6_DATASIZE
#define LWIP_ICMP6_DATASIZE 8
#define LWIP_ICMP6_DATASIZE (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)
#endif
/* Forward declarations */
......@@ -387,26 +387,35 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data,
{
struct pbuf *q;
struct icmp6_hdr *icmp6hdr;
u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE);
u16_t offset;
/* ICMPv6 header + IPv6 header + data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
/* ICMPv6 header + datalen (as much of the offending packet as possible) */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen,
PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
ICMP6_STATS_INC(icmp6.memerr);
return;
}
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
LWIP_ASSERT("check that first pbuf can hold icmp6 header",
(q->len >= (sizeof(struct icmp6_hdr))));
icmp6hdr = (struct icmp6_hdr *)q->payload;
icmp6hdr->type = type;
icmp6hdr->code = code;
icmp6hdr->data = lwip_htonl(data);
/* copy fields from original packet */
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
IP6_HLEN + LWIP_ICMP6_DATASIZE);
/* copy fields from original packet (which may be a chain of pbufs) */
offset = sizeof(struct icmp6_hdr);
while (p && datalen) {
u16_t len = LWIP_MIN(datalen, p->len);
err_t res = pbuf_take_at(q, p->payload, len, offset);
if (res != ERR_OK) break;
datalen -= len;
offset += len;
p = p->next;
}
/* calculate checksum */
icmp6hdr->chksum = 0;
......
......@@ -1305,6 +1305,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
netif = ip6_route(&src_addr, &dest_addr);
dest = &dest_addr;
}
if (netif == NULL) {
......@@ -1364,6 +1365,7 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
netif = ip6_route(&src_addr, &dest_addr);
dest = &dest_addr;
}
if (netif == NULL) {
......
......@@ -781,7 +781,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)));
(rambuf->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);
......
......@@ -253,7 +253,7 @@ mld6_input(struct pbuf *p, struct netif *inp)
while (group != NULL) {
if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
mld6_delayed_report(group, mld_hdr->max_resp_delay);
mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay));
}
group = group->next;
}
......@@ -265,7 +265,7 @@ mld6_input(struct pbuf *p, struct netif *inp)
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
if (group != NULL) {
/* Schedule a report. */
mld6_delayed_report(group, mld_hdr->max_resp_delay);
mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay));
}
}
break; /* ICMP6_TYPE_MLQ */
......
......@@ -693,11 +693,11 @@ nd6_input(struct pbuf *p, struct netif *inp)
}
mtu_opt = (struct mtu_option *)buffer;
mtu32 = lwip_htonl(mtu_opt->mtu);
if ((mtu32 >= 1280) && (mtu32 <= 0xffff)) {
if ((mtu32 >= IP6_MIN_MTU_LENGTH) && (mtu32 <= 0xffff)) {
#if LWIP_ND6_ALLOW_RA_UPDATES
if (inp->mtu) {
/* don't set the mtu for IPv6 higher than the netif driver supports */
inp->mtu6 = LWIP_MIN(inp->mtu, (u16_t)mtu32);
inp->mtu6 = LWIP_MIN(LWIP_MIN(inp->mtu, inp->mtu6), (u16_t)mtu32);
} else {
inp->mtu6 = (u16_t)mtu32;
}
......@@ -766,7 +766,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
rdnss_opt = (struct rdnss_option *)buffer;
num = (rdnss_opt->length - 1) / 2;
for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++, copy_offset += sizeof(ip6_addr_p_t)) {
ip_addr_t rdnss_address;
/* Copy directly from pbuf to get an aligned, zoned copy of the prefix. */
......@@ -1182,15 +1182,27 @@ 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;
const ip6_addr_t *src_addr = NULL;
u16_t lladdr_opt_len;
LWIP_ASSERT("target address is required", target_addr != NULL);
if (!(flags & ND6_SEND_FLAG_ANY_SRC) &&
ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) {
/* Use link-local address as source address. */
src_addr = netif_ip6_addr(netif, 0);
if (!(flags & ND6_SEND_FLAG_ANY_SRC)) {
int i;
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
ip6_addr_netcmp(target_addr, netif_ip6_addr(netif, i))) {
src_addr = netif_ip6_addr(netif, i);
break;
}
}
if (i == LWIP_IPV6_NUM_ADDRESSES) {
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NS: no available src address\n"));
ND6_STATS_INC(nd6.err);
return;
}
/* calculate option length (in 8-byte-blocks) */
lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3;
} else {
......@@ -2300,7 +2312,7 @@ nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif)
return netif_mtu6(netif);
}
return 1280; /* Minimum MTU */
return IP6_MIN_MTU_LENGTH; /* Minimum MTU */
}
......
......@@ -348,10 +348,6 @@ netif_add(struct netif *netif,
#if LWIP_IPV6 && LWIP_IPV6_MLD
netif->mld_mac_filter = NULL;
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
#if ENABLE_LOOPBACK
netif->loop_first = NULL;
netif->loop_last = NULL;
#endif /* ENABLE_LOOPBACK */
/* remember netif specific state information data */
netif->state = state;
......@@ -359,9 +355,16 @@ netif_add(struct netif *netif,
netif->input = input;
NETIF_RESET_HINTS(netif);
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
#if ENABLE_LOOPBACK
netif->loop_first = NULL;
netif->loop_last = NULL;
#if LWIP_LOOPBACK_MAX_PBUFS
netif->loop_cnt_current = 0;
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
netif->reschedule_poll = 0;
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
#if LWIP_IPV4
netif_set_addr(netif, ipaddr, netmask, gw);
......@@ -1031,6 +1034,10 @@ netif_set_link_down(struct netif *netif)
if (netif->flags & NETIF_FLAG_LINK_UP) {
netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
netif->mtu6 = netif->mtu;
#endif
NETIF_LINK_CALLBACK(netif);
#if LWIP_NETIF_EXT_STATUS_CALLBACK
{
......@@ -1062,11 +1069,12 @@ netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callb
/**
* @ingroup netif
* Send an IP packet to be received on the same netif (loopif-like).
* The pbuf is simply copied and handed back to netif->input.
* In multithreaded mode, this is done directly since netif->input must put
* the packet on a queue.
* In callback mode, the packet is put on an internal queue and is fed to
* The pbuf is copied and added to an internal queue which is fed to
* netif->input by netif_poll().
* In multithreaded mode, the call to netif_poll() is queued to be done on the
* TCP/IP thread.
* In callback mode, the user has the responsibility to call netif_poll() in
* the main loop of their application.
*
* @param netif the lwip network interface structure
* @param p the (IP) packet to 'send'
......@@ -1143,6 +1151,12 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
netif->loop_last->next = r;
netif->loop_last = last;
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
if (netif->reschedule_poll) {
schedule_poll = 1;
netif->reschedule_poll = 0;
}
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
} else {
netif->loop_first = r;
netif->loop_last = last;
......@@ -1160,7 +1174,11 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
/* For multithreading environment, schedule a call to netif_poll */
if (schedule_poll) {
tcpip_try_callback((tcpip_callback_fn)netif_poll, netif);
if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) {
SYS_ARCH_PROTECT(lev);
netif->reschedule_poll = 1;
SYS_ARCH_UNPROTECT(lev);
}
}
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
......@@ -1689,6 +1707,7 @@ netif_get_by_index(u8_t idx)
return NULL;
}
#ifndef netif_find
/**
* @ingroup netif
......@@ -1710,6 +1729,10 @@ netif_find(const char *name)
}
num = (u8_t)atoi(&name[2]);
if (!num && (name[2] != '0')) {
/* this means atoi has failed */
return NULL;
}
NETIF_FOREACH(netif) {
if (num == netif->num &&
......@@ -1723,6 +1746,7 @@ netif_find(const char *name)
return NULL;
}
#endif
#if LWIP_NETIF_EXT_STATUS_CALLBACK
/**
* @ingroup netif
......
......@@ -271,7 +271,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
break;
}
case PBUF_RAM: {
u16_t payload_len = (u16_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length));
mem_size_t payload_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length));
mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len);
/* bug #50040: Check for integer overflow when calculating alloc_len */
......@@ -960,55 +960,11 @@ pbuf_dechain(struct pbuf *p)
err_t
pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
{
size_t offset_to = 0, offset_from = 0, len;
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
(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) &&
(p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
/* iterate through pbuf chain */
do {
/* copy one part of the original chain */
if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
/* complete current p_from fits into current p_to */
len = p_from->len - offset_from;
} else {
/* current p_from does not fit into current p_to */
len = p_to->len - offset_to;
}
MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
offset_to += len;
offset_from += len;
LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
if (offset_from >= p_from->len) {
/* on to next p_from (if any) */
offset_from = 0;
p_from = p_from->next;
}
if (offset_to == p_to->len) {
/* on to next p_to (if any) */
offset_to = 0;
p_to = p_to->next;
LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;);
}
if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
/* don't copy more than one packet! */
LWIP_ERROR("pbuf_copy() does not allow packet queues!",
(p_from->next == NULL), return ERR_VAL;);
}
if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
/* don't copy more than one packet! */
LWIP_ERROR("pbuf_copy() does not allow packet queues!",
(p_to->next == NULL), return ERR_VAL;);
}
} while (p_from);
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
return ERR_OK;
LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;);
return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0);
}
/**
......@@ -1031,7 +987,8 @@ pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
err_t
pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
{
size_t offset_to = offset, offset_from = 0, len;
size_t offset_to = offset, offset_from = 0, len_calc;
u16_t len;
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n",
(const void *)p_to, (const void *)p_from, copy_len, offset));
......@@ -1048,12 +1005,12 @@ pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_
/* copy one part of the original chain */
if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
/* complete current p_from fits into current p_to */
len = p_from->len - offset_from;
len_calc = p_from->len - offset_from;
} else {
/* current p_from does not fit into current p_to */
len = p_to->len - offset_to;
len_calc = p_to->len - offset_to;
}
len = LWIP_MIN(copy_len, len);
len = (u16_t)LWIP_MIN(copy_len, len_calc);
MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
offset_to += len;
offset_from += len;
......
......@@ -647,6 +647,7 @@ tcp_abort(struct tcp_pcb *pcb)
* bound to all local IP addresses.
* If another connection is bound to the same port, the function will
* return ERR_USE, otherwise ERR_OK is returned.
* @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
*
* @param pcb the tcp_pcb to bind (no check is done whether this pcb is
* already bound!)
......@@ -889,7 +890,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
lpcb->state = LISTEN;
lpcb->prio = pcb->prio;
lpcb->so_options = pcb->so_options;
lpcb->netif_idx = NETIF_NO_INDEX;
lpcb->netif_idx = pcb->netif_idx;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
#if LWIP_IPV4 && LWIP_IPV6
......@@ -1933,6 +1934,7 @@ tcp_alloc(u8_t prio)
* any of the TCP PCB lists.
* The pcb is not put on any list until binding using tcp_bind().
* If memory is not available for creating the new pcb, NULL is returned.
* @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
*
* @internal: Maybe there should be a idle TCP PCB list where these
* PCBs are put on. Port reservation using tcp_bind() is implemented but
......@@ -1952,6 +1954,7 @@ tcp_new(void)
* Creates a new TCP protocol control block but doesn't
* place it on any of the TCP PCB lists.
* The pcb is not put on any list until binding using tcp_bind().
* @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
*
* @param type IP address type, see @ref lwip_ip_addr_type definitions.
* If you want to listen to IPv4 and IPv6 (dual-stack) connections,
......@@ -2067,6 +2070,7 @@ tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
* @ingroup tcp_raw
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
* @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
*
* @param pcb tcp_pcb to set the accept callback
* @param accept callback function to call for this pcb when LISTENing
......
......@@ -852,8 +852,9 @@ tcp_process(struct tcp_pcb *pcb)
/* Do different things depending on the TCP state. */
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, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %s %"U32_F"\n",
ackno, pcb->snd_nxt, pcb->unacked ? "" : " empty:",
pcb->unacked ? lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0));
/* received SYN ACK with expected sequence number? */
if ((flags & TCP_ACK) && (flags & TCP_SYN)
&& (ackno == pcb->lastack + 1)) {
......
......@@ -913,6 +913,7 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
seg = tcp_create_segment(pcb, p, remainder_flags, lwip_ntohl(useg->tcphdr->seqno) + split, optflags);
if (seg == NULL) {
p = NULL; /* Freed by tcp_create_segment */
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_split_unsent_seg: could not create new TCP segment\n"));
goto memerr;
......@@ -2002,7 +2003,7 @@ tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno,
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
return;
}
tcp_output_fill_options(pcb, p, 0, optlen);
tcp_output_fill_options(pcb, p, 0, 0);
MIB2_STATS_INC(mib2.tcpoutrsts);
......@@ -2096,7 +2097,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
("tcp_keepalive: could not allocate memory for pbuf\n"));
return ERR_MEM;
}
tcp_output_fill_options(pcb, p, 0, optlen);
tcp_output_fill_options(pcb, p, 0, 0);
err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
......@@ -2178,7 +2179,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
pcb->snd_nxt = snd_nxt;
}
tcp_output_fill_options(pcb, p, 0, optlen);
tcp_output_fill_options(pcb, p, 0, 0);
err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
......
......@@ -1001,9 +1001,13 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{
/* port matches that of PCB in list and REUSEADDR not set -> reject */
if ((ipcb->local_port == port) &&
(((IP_GET_TYPE(&ipcb->local_ip) == IP_GET_TYPE(ipaddr)) &&
/* IP address matches or any IP used? */
(ip_addr_cmp(&ipcb->local_ip, ipaddr) || ip_addr_isany(ipaddr) ||
ip_addr_isany(&ipcb->local_ip))) {
(ip_addr_cmp(&ipcb->local_ip, ipaddr) ||
ip_addr_isany(ipaddr) ||
ip_addr_isany(&ipcb->local_ip))) ||
(IP_GET_TYPE(&ipcb->local_ip) == IPADDR_TYPE_ANY) ||
(IP_GET_TYPE(ipaddr) == IPADDR_TYPE_ANY))) {
/* other PCB already binds to this local IP and port */
LWIP_DEBUGF(UDP_DEBUG,
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
......@@ -1212,6 +1216,7 @@ udp_remove(struct udp_pcb *pcb)
* Creates a new UDP pcb which can be used for UDP communication. The
* pcb is not active until it has either been bound to a local address
* or connected to a remote address.
* @see MEMP_NUM_UDP_PCB
*
* @return The UDP PCB which was created. NULL if the PCB data structure
* could not be allocated.
......@@ -1246,7 +1251,8 @@ udp_new(void)
* Create a UDP PCB for specific IP type.
* The pcb is not active until it has either been bound to a local address
* or connected to a remote address.
*
* @see MEMP_NUM_UDP_PCB
*
* @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.
......
......@@ -129,6 +129,11 @@ err_t altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr,
ip_addr_t *altcp_get_ip(struct altcp_pcb *conn, int local);
u16_t altcp_get_port(struct altcp_pcb *conn, int local);
#if LWIP_TCP_KEEPALIVE
void altcp_keepalive_disable(struct altcp_pcb *conn);
void altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
#endif
#ifdef LWIP_DEBUG
enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn);
#endif
......
......@@ -61,7 +61,22 @@ extern "C" {
struct altcp_tls_config;
/** @ingroup altcp_tls
* Create an ALTCP_TLS server configuration handle
* Create an ALTCP_TLS server configuration handle prepared for multiple certificates
*/
struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count);
/** @ingroup altcp_tls
* Add a certificate to an ALTCP_TLS server configuration handle
*/
err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config,
const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len);
/** @ingroup altcp_tls
* Create an ALTCP_TLS server configuration handle with one certificate
* (short version of calling @ref altcp_tls_create_config_server and
* @ref altcp_tls_config_server_add_privkey_cert)
*/
struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
......@@ -84,6 +99,17 @@ struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca,
*/
void altcp_tls_free_config(struct altcp_tls_config *conf);
/** @ingroup altcp_tls
* Free an ALTCP_TLS global entropy instance.
* All ALTCP_TLS configuration are linked to one altcp_tls_entropy_rng structure
* that handle an unique system entropy & ctr_drbg instance.
* This function allow application to free this altcp_tls_entropy_rng structure
* when all configuration referencing it were destroyed.
* This function does nothing if some ALTCP_TLS configuration handle are still
* active.
*/
void altcp_tls_free_entropy(void);
/** @ingroup altcp_tls
* Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP)
*/
......
......@@ -55,11 +55,49 @@
#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_OFF
#endif
/** Set a session timeout in seconds for the basic session cache
/** Configure lwIP debug level of the mbedTLS library */
#ifndef ALTCP_MBEDTLS_LIB_DEBUG
#define ALTCP_MBEDTLS_LIB_DEBUG LWIP_DBG_OFF
#endif
/** Configure minimum internal debug level of the mbedTLS library */
#ifndef ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN
#define ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN 0
#endif
/** Enable the basic session cache
* ATTENTION: Using a session cache can lower security by reusing keys!
*/
#ifndef ALTCP_MBEDTLS_USE_SESSION_CACHE
#define ALTCP_MBEDTLS_USE_SESSION_CACHE 0
#endif
/** Maximum cache size of the basic session cache */
#ifndef ALTCP_MBEDTLS_SESSION_CACHE_SIZE
#define ALTCP_MBEDTLS_SESSION_CACHE_SIZE 30
#endif
/** Set a session timeout in seconds for the basic session cache */
#ifndef ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 0
#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS (60 * 60)
#endif
/** Use session tickets to speed up connection setup (needs
* MBEDTLS_SSL_SESSION_TICKETS enabled in mbedTLS config).
* ATTENTION: Using session tickets can lower security by reusing keys!
*/
#ifndef ALTCP_MBEDTLS_USE_SESSION_TICKETS
#define ALTCP_MBEDTLS_USE_SESSION_TICKETS 0
#endif
/** Session ticket cipher */
#ifndef ALTCP_MBEDTLS_SESSION_TICKET_CIPHER
#define ALTCP_MBEDTLS_SESSION_TICKET_CIPHER MBEDTLS_CIPHER_AES_256_GCM
#endif
/** Maximum timeout for session tickets */
#ifndef ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS
#define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS (60 * 60 * 24)
#endif
#endif /* LWIP_ALTCP */
......
......@@ -67,11 +67,11 @@ void sntp_setservername(u8_t idx, const char *server);
const char *sntp_getservername(u8_t idx);
#endif /* SNTP_SERVER_DNS */
#if SNTP_GET_SERVERS_FROM_DHCP
#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
void sntp_servermode_dhcp(int set_servers_from_dhcp);
#else /* SNTP_GET_SERVERS_FROM_DHCP */
#else /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
#define sntp_servermode_dhcp(x)
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
#ifdef __cplusplus
}
......
......@@ -67,6 +67,12 @@
#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV
#endif
/** Set this to 1 to implement the callback function called by dhcpv6 when
* NTP servers are received. */
#if !defined SNTP_GET_SERVERS_FROM_DHCPV6 || defined __DOXYGEN__
#define SNTP_GET_SERVERS_FROM_DHCPV6 LWIP_DHCP6_GET_NTP_SRV
#endif
/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers
* One server address/name can be defined as default if SNTP_SERVER_DNS == 1:
* \#define SNTP_SERVER_ADDRESS "pool.ntp.org"
......
......@@ -120,9 +120,7 @@
#endif /* LWIP_NOASSERT */
#ifndef LWIP_ERROR
#ifndef LWIP_NOASSERT
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
#elif defined LWIP_DEBUG
#ifdef LWIP_DEBUG
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message))
#else
#define LWIP_PLATFORM_ERROR(message)
......
......@@ -48,8 +48,11 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef LWIP_SOCKET_STDINCLUDE
#ifndef IF_NAMESIZE
#define IF_NAMESIZE NETIF_NAMESIZE
#endif
#endif /* LWIP_SOCKET_STDINCLUDE */
char * lwip_if_indextoname(unsigned int ifindex, char *ifname);
unsigned int lwip_if_nametoindex(const char *ifname);
......
......@@ -54,7 +54,7 @@ extern "C" {
/** x.X.x: Minor version of the stack */
#define LWIP_VERSION_MINOR 1
/** x.x.X: Revision of the stack */
#define LWIP_VERSION_REVISION 2
#define LWIP_VERSION_REVISION 3
/** For release candidates, this is set to 1..254
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
......
......@@ -386,6 +386,10 @@ struct netif {
#if LWIP_LOOPBACK_MAX_PBUFS
u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
/* Used if the original scheduling failed. */
u8_t reschedule_poll;
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
};
......@@ -451,7 +455,7 @@ void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
#define netif_set_flags(netif, set_flags) do { (netif)->flags = (u8_t)((netif)->flags | (set_flags)); } while(0)
#define netif_clear_flags(netif, clr_flags) do { (netif)->flags = (u8_t)((netif)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
#define netif_is_flag_set(nefif, flag) (((netif)->flags & (flag)) != 0)
#define netif_is_flag_set(netif, flag) (((netif)->flags & (flag)) != 0)
void netif_set_up(struct netif *netif);
void netif_set_down(struct netif *netif);
......
......@@ -1545,7 +1545,7 @@
* TCP_MSS, IP header, and link header.
*/
#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+PBUF_IP_HLEN+PBUF_TRANSPORT_HLEN+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
#endif
/**
......@@ -1555,6 +1555,14 @@
#if !defined LWIP_PBUF_REF_T || defined __DOXYGEN__
#define LWIP_PBUF_REF_T u8_t
#endif
/**
* LWIP_PBUF_CUSTOM_DATA: Store private data on pbufs (e.g. timestamps)
* This extends struct pbuf so user can store custom data on every pbuf.
*/
#if !defined LWIP_PBUF_CUSTOM_DATA || defined __DOXYGEN__
#define LWIP_PBUF_CUSTOM_DATA
#endif
/**
* @}
*/
......@@ -1912,11 +1920,8 @@
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
* writing from a 2nd thread and closing from a 3rd thread at the same time.
* ATTENTION: This is currently really alpha! Some requirements:
* - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from
* multiple threads at once
* - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox
* and prevent a task pending on this during/after deletion
* LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from
* multiple threads at once!
*/
#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__
#define LWIP_NETCONN_FULLDUPLEX 0
......@@ -2446,7 +2451,7 @@
* network startup.
*/
#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__
#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1
#define LWIP_IPV6_SEND_ROUTER_SOLICIT LWIP_IPV6
#endif
/**
......@@ -2491,10 +2496,12 @@
/**
* LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
* ICMPv6 error messages.
* ICMPv6 error messages (0 = default of IP6_MIN_MTU_LENGTH)
* ATTENTION: RFC4443 section 2.4 says IP6_MIN_MTU_LENGTH is a MUST,
* so override this only if you absolutely have to!
*/
#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__
#define LWIP_ICMP6_DATASIZE 8
#define LWIP_ICMP6_DATASIZE 0
#endif
/**
......
......@@ -219,6 +219,9 @@ struct pbuf {
/** For incoming packets, this contains the input netif's index */
u8_t if_idx;
/** In case the user needs to store data custom data on a pbuf */
LWIP_PBUF_CUSTOM_DATA
};
......
......@@ -85,6 +85,11 @@ typedef err_t (*altcp_get_tcp_addrinfo_fn)(struct altcp_pcb *conn, int local, ip
typedef ip_addr_t *(*altcp_get_ip_fn)(struct altcp_pcb *conn, int local);
typedef u16_t (*altcp_get_port_fn)(struct altcp_pcb *conn, int local);
#if LWIP_TCP_KEEPALIVE
typedef void (*altcp_keepalive_disable_fn)(struct altcp_pcb *conn);
typedef void (*altcp_keepalive_enable_fn)(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
#endif
#ifdef LWIP_DEBUG
typedef enum tcp_state (*altcp_dbg_get_tcp_state_fn)(struct altcp_pcb *conn);
#endif
......@@ -111,6 +116,10 @@ struct altcp_functions {
altcp_get_tcp_addrinfo_fn addrinfo;
altcp_get_ip_fn getip;
altcp_get_port_fn getport;
#if LWIP_TCP_KEEPALIVE
altcp_keepalive_disable_fn keepalive_disable;
altcp_keepalive_enable_fn keepalive_enable;
#endif
#ifdef LWIP_DEBUG
altcp_dbg_get_tcp_state_fn dbg_get_tcp_state;
#endif
......@@ -133,6 +142,10 @@ void altcp_default_dealloc(struct altcp_pcb *conn);
err_t altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
ip_addr_t *altcp_default_get_ip(struct altcp_pcb *conn, int local);
u16_t altcp_default_get_port(struct altcp_pcb *conn, int local);
#if LWIP_TCP_KEEPALIVE
void altcp_default_keepalive_disable(struct altcp_pcb *conn);
void altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
#endif
#ifdef LWIP_DEBUG
enum tcp_state altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn);
#endif
......
......@@ -146,6 +146,8 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
#define ICMP6_HLEN 8
/** This is the ICMP6 header adapted for echo req/resp. */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
......
......@@ -44,6 +44,8 @@
extern "C" {
#endif
#define IP6_MIN_MTU_LENGTH 1280
/** This is the packed version of ip6_addr_t,
used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
......
......@@ -44,6 +44,13 @@
#define PPPOE_SUPPORT 0
#endif
/**
* PPPOE_SCNAME_SUPPORT==1: Enable PPP Over Ethernet Service Name and Concentrator Name support
*/
#ifndef PPPOE_SCNAME_SUPPORT
#define PPPOE_SCNAME_SUPPORT 0
#endif
/**
* PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP
*/
......
......@@ -149,10 +149,10 @@ struct pppoe_softc {
u16_t sc_session; /* PPPoE session id */
u8_t sc_state; /* discovery phase or session connected */
#ifdef PPPOE_TODO
u8_t *sc_service_name; /* if != NULL: requested name of service */
u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */
#endif /* PPPOE_TODO */
#if PPPOE_SCNAME_SUPPORT
const char *sc_service_name; /* if != NULL: requested name of service */
const char *sc_concentrator_name; /* if != NULL: requested concentrator id */
#endif /* PPPOE_SCNAME_SUPPORT */
u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */
u8_t sc_ac_cookie_len; /* length of cookie data */
#ifdef PPPOE_SERVER
......
......@@ -881,7 +881,7 @@ lowpan6_if_init(struct netif *netif)
MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
/* maximum transfer unit */
netif->mtu = 1280;
netif->mtu = IP6_MIN_MTU_LENGTH;
/* broadcast capability */
netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */;
......
......@@ -417,7 +417,7 @@ rfc7668_if_init(struct netif *netif)
MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
/* maximum transfer unit, set according to RFC7668 ch2.4 */
netif->mtu = 1280;
netif->mtu = IP6_MIN_MTU_LENGTH;
/* no flags set (no broadcast, ethernet,...)*/
netif->flags = 0;
......
......@@ -440,7 +440,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
if ((lowpan6_buffer[0] & 0x18) == 0x00) {
header_temp = ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | \
(lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%2x, Flowlabel+DSCP: 0x%8X\n", \
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%"X8_F", Flowlabel+DSCP: 0x%8"X32_F"\n", \
lowpan6_buffer[lowpan6_offset],header_temp));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], header_temp);
/* increase offset, processed 4 bytes here:
......@@ -448,14 +448,14 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
lowpan6_offset += 4;
} else if ((lowpan6_buffer[0] & 0x18) == 0x08) {
header_temp = ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%2x, Flowlabel: 0x%2X, DSCP ignored\n", \
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%"X8_F", Flowlabel: 0x%2"X32_F", DSCP ignored\n", \
lowpan6_buffer[lowpan6_offset] & 0xc0,header_temp));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, header_temp);
/* increase offset, processed 3 bytes here:
* TF=01: ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.*/
lowpan6_offset += 3;
} else if ((lowpan6_buffer[0] & 0x18) == 0x10) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%2x, Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset]));
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%"X8_F", Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset]));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0);
/* increase offset, processed 1 byte here:
* ECN + DSCP (1 byte), Flow Label is elided.*/
......@@ -564,7 +564,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
#if LWIP_6LOWPAN_NUM_CONTEXTS > 0
ip6hdr->src.addr[0] = lowpan6_contexts[i].addr[0];
ip6hdr->src.addr[1] = lowpan6_contexts[i].addr[1];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8X, %8X\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1]));
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8"X32_F", %8"X32_F"\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1]));
#else
LWIP_UNUSED_ARG(lowpan6_contexts);
#endif
......
......@@ -216,7 +216,8 @@ static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protoc
/***********************************/
#if PPP_AUTH_SUPPORT
void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) {
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD", pcb->phase == PPP_PHASE_DEAD);
#if PAP_SUPPORT
pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP);
#endif /* PAP_SUPPORT */
......@@ -238,6 +239,8 @@ void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *pas
#if MPPE_SUPPORT
/* Set MPPE configuration */
void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) {
LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD", pcb->phase == PPP_PHASE_DEAD);
if (flags == PPP_MPPE_DISABLE) {
pcb->settings.require_mppe = 0;
return;
......
......@@ -175,8 +175,10 @@ ppp_pcb *pppoe_create(struct netif *pppif,
{
ppp_pcb *ppp;
struct pppoe_softc *sc;
#if !PPPOE_SCNAME_SUPPORT
LWIP_UNUSED_ARG(service_name);
LWIP_UNUSED_ARG(concentrator_name);
#endif /* !PPPOE_SCNAME_SUPPORT */
LWIP_ASSERT_CORE_LOCKED();
sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF);
......@@ -193,6 +195,10 @@ ppp_pcb *pppoe_create(struct netif *pppif,
memset(sc, 0, sizeof(struct pppoe_softc));
sc->pcb = ppp;
sc->sc_ethif = ethif;
#if PPPOE_SCNAME_SUPPORT
sc->sc_service_name = service_name;
sc->sc_concentrator_name = concentrator_name;
#endif /* PPPOE_SCNAME_SUPPORT */
/* put the new interface at the head of the list */
sc->next = pppoe_softc_list;
pppoe_softc_list = sc;
......@@ -300,15 +306,6 @@ pppoe_destroy(ppp_pcb *ppp, void *ctx)
break;
}
}
#ifdef PPPOE_TODO
if (sc->sc_concentrator_name) {
mem_free(sc->sc_concentrator_name);
}
if (sc->sc_service_name) {
mem_free(sc->sc_service_name);
}
#endif /* PPPOE_TODO */
LWIP_MEMPOOL_FREE(PPPOE_IF, sc);
return ERR_OK;
......@@ -757,13 +754,13 @@ pppoe_send_padi(struct pppoe_softc *sc)
struct pbuf *pb;
u8_t *p;
int len;
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
int l1 = 0, l2 = 0; /* XXX: gcc */
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
/* calculate length of frame (excluding ethernet header + pppoe header) */
len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
if (sc->sc_service_name != NULL) {
l1 = (int)strlen(sc->sc_service_name);
len += l1;
......@@ -772,7 +769,7 @@ pppoe_send_padi(struct pppoe_softc *sc)
l2 = (int)strlen(sc->sc_concentrator_name);
len += 2 + 2 + l2;
}
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
......@@ -787,24 +784,24 @@ pppoe_send_padi(struct pppoe_softc *sc)
/* fill in pkt */
PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
if (sc->sc_service_name != NULL) {
PPPOE_ADD_16(p, l1);
MEMCPY(p, sc->sc_service_name, l1);
p += l1;
} else
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
{
PPPOE_ADD_16(p, 0);
}
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
if (sc->sc_concentrator_name != NULL) {
PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
PPPOE_ADD_16(p, l2);
MEMCPY(p, sc->sc_concentrator_name, l2);
p += l2;
}
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
PPPOE_ADD_16(p, sizeof(sc));
MEMCPY(p, &sc, sizeof sc);
......@@ -982,17 +979,17 @@ pppoe_send_padr(struct pppoe_softc *sc)
struct pbuf *pb;
u8_t *p;
size_t len;
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
size_t l1 = 0; /* XXX: gcc */
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
l1 = strlen(sc->sc_service_name);
len += l1;
}
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
if (sc->sc_ac_cookie_len > 0) {
len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */
}
......@@ -1006,13 +1003,13 @@ pppoe_send_padr(struct pppoe_softc *sc)
p = (u8_t*)pb->payload;
PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
#ifdef PPPOE_TODO
#if PPPOE_SCNAME_SUPPORT
if (sc->sc_service_name != NULL) {
PPPOE_ADD_16(p, l1);
MEMCPY(p, sc->sc_service_name, l1);
p += l1;
} else
#endif /* PPPOE_TODO */
#endif /* PPPOE_SCNAME_SUPPORT */
{
PPPOE_ADD_16(p, 0);
}
......
......@@ -365,7 +365,23 @@ sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
}
#if LWIP_NETCONN_SEM_PER_THREAD
#error LWIP_NETCONN_SEM_PER_THREAD==1 not supported
/* Simple implementation of this: unit tests only support one thread */
static sys_sem_t global_netconn_sem;
sys_sem_t* sys_arch_netconn_sem_get(void)
{
return &global_netconn_sem;
}
void sys_arch_netconn_sem_alloc(void)
{
sys_sem_new(&global_netconn_sem, 0);
}
void sys_arch_netconn_sem_free(void)
{
sys_sem_free(&global_netconn_sem);
}
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
#endif /* !NO_SYS */
......@@ -68,5 +68,12 @@ void test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn);
/* current time */
extern u32_t lwip_sys_now;
sys_sem_t* sys_arch_netconn_sem_get(void);
void sys_arch_netconn_sem_alloc(void);
void sys_arch_netconn_sem_free(void);
#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get()
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc()
#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free()
#endif /* LWIP_HDR_TEST_SYS_ARCH_H */
......@@ -9,7 +9,7 @@
#error "This tests needs LWIP_NETIF_EXT_STATUS_CALLBACK enabled"
#endif
struct netif net_test;
static struct netif net_test;
/* Setups/teardown functions */
......@@ -215,13 +215,67 @@ START_TEST(test_netif_extcallbacks)
}
END_TEST
START_TEST(test_netif_flag_set)
{
ip4_addr_t addr;
ip4_addr_t netmask;
ip4_addr_t gw;
LWIP_UNUSED_ARG(_i);
IP4_ADDR(&addr, 0, 0, 0, 0);
IP4_ADDR(&netmask, 0, 0, 0, 0);
IP4_ADDR(&gw, 0, 0, 0, 0);
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
fail_if(netif_is_flag_set(&net_test, NETIF_FLAG_UP));
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_BROADCAST));
fail_if(netif_is_flag_set(&net_test, NETIF_FLAG_LINK_UP));
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_ETHARP));
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_ETHERNET));
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_IGMP));
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_MLD6));
netif_remove(&net_test);
}
END_TEST
START_TEST(test_netif_find)
{
struct netif net0;
struct netif net1;
LWIP_UNUSED_ARG(_i);
/* No netifs available */
fail_unless(netif_find("ch0") == NULL);
/* Add netifs with known names */
fail_unless(netif_add_noaddr(&net0, NULL, testif_init, ethernet_input) == &net0);
net0.num = 0;
fail_unless(netif_add_noaddr(&net1, NULL, testif_init, ethernet_input) == &net1);
net1.num = 1;
fail_unless(netif_find("ch0") == &net0);
fail_unless(netif_find("CH0") == NULL);
fail_unless(netif_find("ch1") == &net1);
fail_unless(netif_find("ch3") == NULL);
/* atoi failure is not treated as zero */
fail_unless(netif_find("chX") == NULL);
fail_unless(netif_find("ab0") == NULL);
netif_remove(&net0);
netif_remove(&net1);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
netif_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_netif_extcallbacks)
TESTFUNC(test_netif_extcallbacks),
TESTFUNC(test_netif_flag_set),
TESTFUNC(test_netif_find)
};
return create_suite("NETIF", tests, sizeof(tests)/sizeof(testfunc), netif_setup, netif_teardown);
}
......@@ -6,7 +6,7 @@
#include "lwip/etharp.h"
#include "netif/ethernet.h"
struct netif net_test;
static struct netif net_test;
static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
......
......@@ -287,6 +287,43 @@ START_TEST(test_ip6_lladdr)
}
END_TEST
/* Reproduces bug #57374 */
START_TEST(test_ip6_frag_pbuf_len_assert)
{
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
struct pbuf *payload, *hdr;
err_t err;
int i;
/* Configure and enable local address */
test_netif6.mtu = 1500;
netif_set_up(&test_netif6);
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
/* Create packet with lots of small pbufs around mtu limit */
payload = pbuf_alloc(PBUF_RAW, 1400, PBUF_POOL);
fail_unless(payload != NULL);
for (i = 0; i < 16; i++) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, 32, PBUF_RAM);
fail_unless(p != NULL);
pbuf_cat(payload, p);
}
/* Prefix with header like UDP would */
hdr = pbuf_alloc(PBUF_IP, 8, PBUF_RAM);
fail_unless(hdr != NULL);
pbuf_chain(hdr, payload);
/* Send it and don't crash while fragmenting */
err = ip6_output_if_src(hdr, ip_2_ip6(&my_addr), ip_2_ip6(&peer_addr), 15, 0, IP_PROTO_UDP, &test_netif6);
fail_unless(err == ERR_OK);
pbuf_free(hdr);
pbuf_free(payload);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
ip6_suite(void)
......@@ -296,7 +333,8 @@ ip6_suite(void)
TESTFUNC(test_ip6_aton_ipv4mapped),
TESTFUNC(test_ip6_ntoa_ipv4mapped),
TESTFUNC(test_ip6_ntoa),
TESTFUNC(test_ip6_lladdr)
TESTFUNC(test_ip6_lladdr),
TESTFUNC(test_ip6_frag_pbuf_len_assert)
};
return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), ip6_setup, ip6_teardown);
}
......
......@@ -13,6 +13,7 @@
#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0)
#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL)
#if (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13)
typedef struct {
TFun func;
const char *name;
......@@ -24,6 +25,15 @@ typedef struct {
#define tcase_add_named_test(tc,tf) \
_tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1)
#else
/* From 0.13.0 check keeps track of the method name internally */
typedef const TTest * testfunc;
#define TESTFUNC(x) x
#define tcase_add_named_test(tc,tf) tcase_add_test(tc,tf)
#endif
/** typedef for a function returning a test suite */
typedef Suite* (suite_getter_fn)(void);
......
......@@ -46,6 +46,7 @@
#define LWIP_NETCONN !NO_SYS
#define LWIP_SOCKET !NO_SYS
#define LWIP_NETCONN_FULLDUPLEX LWIP_SOCKET
#define LWIP_NETCONN_SEM_PER_THREAD 1
#define LWIP_NETBUF_RECVINFO 1
#define LWIP_HAVE_LOOPIF 1
#define TCPIP_THREAD_TEST
......
......@@ -335,13 +335,138 @@ START_TEST(test_udp_broadcast_rx_with_2_netifs)
}
END_TEST
START_TEST(test_udp_bind)
{
struct udp_pcb* pcb1;
struct udp_pcb* pcb2;
ip_addr_t ip1;
ip_addr_t ip2;
err_t err1;
err_t err2;
LWIP_UNUSED_ARG(_i);
/* bind on same port using different IP address types */
ip_addr_set_any_val(0, ip1);
ip_addr_set_any_val(1, ip2);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_OK);
udp_remove(pcb1);
udp_remove(pcb2);
/* bind on same port using SAME IPv4 address type */
ip_addr_set_any_val(0, ip1);
ip_addr_set_any_val(0, ip2);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_USE);
udp_remove(pcb1);
udp_remove(pcb2);
/* bind on same port using SAME IPv6 address type */
ip_addr_set_any_val(1, ip1);
ip_addr_set_any_val(1, ip2);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_USE);
udp_remove(pcb1);
udp_remove(pcb2);
/* Bind with different IP address type */
ip_addr_set_any_val(0, ip1);
ip_addr_set_any_val(1, ip2);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_OK);
udp_remove(pcb1);
udp_remove(pcb2);
/* Bind with different IP numbers */
IP_ADDR4(&ip1, 1, 2, 3, 4);
IP_ADDR4(&ip2, 4, 3, 2, 1);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_OK);
udp_remove(pcb1);
udp_remove(pcb2);
/* Bind with same IP numbers */
IP_ADDR4(&ip1, 1, 2, 3, 4);
IP_ADDR4(&ip2, 1, 2, 3, 4);
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_USE);
udp_remove(pcb1);
udp_remove(pcb2);
/* bind on same port using ANY + IPv4 */
ip1 = *IP_ANY_TYPE;
IP_ADDR4(&ip2, 1, 2, 3, 4);
pcb1 = udp_new_ip_type(IPADDR_TYPE_ANY);
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
err1 = udp_bind(pcb1, &ip1, 2105);
err2 = udp_bind(pcb2, &ip2, 2105);
fail_unless(err1 == ERR_OK);
fail_unless(err2 == ERR_USE);
udp_remove(pcb1);
udp_remove(pcb2);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
udp_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_udp_new_remove),
TESTFUNC(test_udp_broadcast_rx_with_2_netifs)
TESTFUNC(test_udp_broadcast_rx_with_2_netifs),
TESTFUNC(test_udp_bind)
};
return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册