Compare commits

...

250 Commits

Author SHA1 Message Date
goldsimon
c0862d6074 Fixed LWIP_VERSION define for 2.0.2 2017-03-13 13:27:00 +01:00
goldsimon
ea2f6fb57c Add CHANGELOG for 2.0.2 2017-03-13 10:26:42 +01:00
Dirk Ziegelmeier
b307fea1b9 Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191: "IPv4-mapped IPv6 address"
(cherry picked from commit 4d8fec3b67)

Conflicts:
	src/core/ipv6/ip6.c
2017-03-13 09:28:46 +01:00
Joel Cunningham
c31bd404e2 Fix unit test with assumed congestion avoidance
test_tcp_fast_rexmit_wraparound correctness relied on the congestion
window being in congestion avoidance so that only a single TCP_MSS
segment is sent upon ACKing the first segment.

It's not known whether the test was relying tcp_alloc() to set ssthresh
to 0 and thus start in congestion avoidance or if the test was working by
accident until changes in b90a54f989

This fixes the test by enforcing the requirement of starting in
congestion avoidance

Signed-off-by: goldsimon <goldsimon@gmx.de>
(cherry picked from commit 8bf402fd67)
2017-03-13 09:14:38 +01:00
goldsimon
0381849624 tcp unit tests: fixed that tcp_teardown() could lead to accessing a netif pointer that is not valid any more (netif added in test function stored on stack)
(cherry picked from commit e9e9ec23b8)
2017-03-13 09:14:24 +01:00
goldsimon
19d56b4096 tcp: watch out for pcb->nrtx overflows and tcp_backoff indexing overflow
(cherry picked from commit 7ffe5bfb3c)
2017-03-13 09:14:23 +01:00
David van Moolenbroek
66db517a28 tcp: do not keep sending SYNs when getting ACKs
If a locally generated TCP SYN packet is replied to with an ACK
packet, lwIP immediately sends a RST packet followed by resending the
SYN packet.  This is expected, but on loopback interfaces the resent
SYN packet may immediately get another ACK reply, typically when the
other endpoint is in TIME_WAIT state (which ignores the RSTs).  The
result is an endless loop of SYN, ACK, RST packets.

This patch applies the normal SYN retransmission limit in this
scenario, such that the endless loop is limited to a brief storm.

(cherry picked from commit 5827c168c2)
2017-03-13 09:14:22 +01:00
Joel Cunningham
2452bc9336 bug #50476: initialize ssthresh to TCP_SND_BUF
This commit changes ssthresh to be the largest effective congestion
window (amount of in-flight data). This follows the guidance of RFC
5681 which recommends setting ssthresh arbitrarily high.

LwIP was previously using the receive window value at the end of the
3-way handshake and in the case of an active open where the receiver
used window scaling and/or window auto-tuning, this resulted in a very
small ssthresh value even though the window ramped up once the connection
was established

(cherry picked from commit b90a54f989)
2017-03-13 09:13:41 +01:00
Sylvain Rochet
2848b17e80 PPP: remove unused and confusing return values other than ERR_OK for ppp_connect and ppp_listen
User should not use ppp_connect or ppp_listen return value to retry
later, it must wait for the callback to be called. This is primarily
done this way to have a consistent behavior with and without the
holdoff feature.

Remove returned error value from PPP link level API connect and listen
callbacks because we are not using them anymore, then make ppp_connect
or ppp_listen to always return ERR_OK, thus we are not breaking the PPP
user API.

We don't need the return code here, all PPP link level drivers can't
fail at all (e.g. PPPoS) or retry if necessary (PPPoE and PPPoL2TP).

(cherry picked from commit e16d10ade6)
2017-03-13 09:13:17 +01:00
goldsimon
c71c9882c2 arch.h: include <limits.h> if it exists (at least INT_MAX is used)
(cherry picked from commit aff1935e40)
2017-03-13 09:13:07 +01:00
Dirk Ziegelmeier
40fbd6bc24 One enum icmp_te_type member is not in doxygen docs - fix it.
(cherry picked from commit 927990d94e)
2017-03-13 09:12:30 +01:00
goldsimon
df7485de1c lwip_sendmsg/tcp: prevent PSH until all iovecs are enqueued
(cherry picked from commit 1b3aaef525)
2017-03-13 09:12:08 +01:00
goldsimon
fe6e1bd4af httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved is called nested from httpd_post_receive_data() (bug #50424)
# Conflicts:
#	CHANGELOG
2017-03-01 22:15:59 +01:00
goldsimon
168fa1c38a Fix compiling httpd for LWIP_HTTPD_SUPPORT_POST==1 (assigning int to u16_t) 2017-03-01 22:15:42 +01:00
goldsimon
f0975b3c59 make tcp apps depend on LWIP_CALLBACK_API, too 2017-03-01 22:15:18 +01:00
goldsimon
563932b888 tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb
# Conflicts:
#	CHANGELOG
2017-03-01 22:15:07 +01:00
goldsimon
8849a443a4 pbuf_ref: assert-check for 'ref' overflow
(cherry picked from commit 76763c9bcd)
2017-02-27 12:31:13 +01:00
goldsimon
e318688195 Improved DNS_LOCAL_HOSTLIST interface (bug #50325)
(cherry picked from commit deaa6e9406)

Conflicts:
	CHANGELOG
2017-02-27 12:30:38 +01:00
goldsimon
fa8b6a92b4 Fix portable initialization of non-dynamic DNS_LOCAL_HOSTLIST
(cherry picked from commit 19d63e6aa0)
2017-02-27 12:30:30 +01:00
sg
2ca39c275a LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274)
(cherry picked from commit 6dca664217)

Conflicts:
	CHANGELOG
2017-02-27 12:29:23 +01:00
Joel Cunningham
4d1d567ab7 Fix comment typo from bug #47485
tcp_close_shutdown_impl() should be tcp_close_shutdown_fin()

(cherry picked from commit 0b257f71e7)
2017-02-27 12:28:18 +01:00
goldsimon
8927cda2f8 For tiny targtes, LWIP_RAND is optional -> fix compile time checks
(cherry picked from commit 693a74c286)
2017-02-27 12:27:47 +01:00
Dirk Ziegelmeier
bc78251f4a My documentation changes forced the usage of rand() function, which is not desired
By default, the code that does NOT need LWIP_RAND() is active now

(cherry picked from commit 06c84cb110)
2017-02-27 12:27:30 +01:00
David van Moolenbroek
0a3e4cd10e tcp: fix accept event on closed listening PCBs
If LWIP_CALLBACK_API is not defined, but TCP_LISTEN_BACKLOG is, then
the LWIP_EVENT_ACCEPT TCP event may be triggered for closed listening
sockets.  This case is just as disastrous for the event API as it is
for the callback API, as there is no way for the event hook to tell
whether the listening PCB is still around.  Add the same protection
against this case for TCP_LISTEN_BACKLOG as was already in place for
LWIP_CALLBACK_API.

Also remove one NULL check for LWIP_CALLBACK_API that had already
become redundant for all callers, making the TCP_EVENT_ACCEPT code
for that callback wrapper more in line with the rest of the wrappers.

(cherry picked from commit 240cf62056)
2017-02-27 12:25:52 +01:00
Dirk Ziegelmeier
76efa271e6 Implement task #14367: Hooks need a better place to be defined
We now have a #define for a header file name that is #included in every .c file that provides hooks.
2017-02-27 12:25:08 +01:00
goldsimon
b3293d903e Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying to send FIN from tcp_fasttmr
(cherry picked from commit bc07fd9db5)

Conflicts:
	CHANGELOG
2017-02-27 12:24:51 +01:00
Dirk Ziegelmeier
5ef8a3cb60 igmp.c: igmp_lookup_group() should be static
(cherry picked from commit 702091d548)
2017-02-27 12:23:39 +01:00
sg
01c2e43c5c Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on invalid/reused socket) by not allowing to reallocate a socket that has "select_waiting != 0"
(cherry picked from commit c1c470fc4c)
2017-02-27 12:23:04 +01:00
goldsimon
0b7bef5420 http_add_connection: add connections to the front to be faster (and really fix bug #50059)
(cherry picked from commit ea093d3a53)
2017-02-27 12:22:42 +01:00
goldsimon
3c4aec99a4 Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs. LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED)
(cherry picked from commit 5743864744)
2017-02-27 12:22:42 +01:00
Luc Revardel
dc38e21a70 Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even if last reporter)
Signed-off-by: sg <goldsimon@gmx.de>
(cherry picked from commit 819bfbb943)
2017-02-27 12:22:41 +01:00
David van Moolenbroek
d471e5f89e Patch #9250 (slightly changed): fix source substitution in ip6_output_if() (broken in 2014 with be75c483d0)
Signed-off-by: sg <goldsimon@gmx.de>
(cherry picked from commit fffd61c746)
2017-02-27 12:22:03 +01:00
sg
99ef13f2be Fixed bug #50090 (ast_unsent->oversize_left can become wrong value in tcp_write error path)
(cherry picked from commit 21737f57e5)
2017-02-27 12:21:31 +01:00
Dirk Ziegelmeier
bb2b2be454 Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails
The tests were in to catch user errors, but they seem to get in the way of application programming :-)
The checks in *_send() remain active to catch when PCB source and destination address types do not match

(cherry picked from commit ff04c2046e)
2017-02-27 12:20:01 +01:00
goldsimon
faa7a21a83 Fix comment on lwip_shutdown() (it's not unimplemented any more)
(cherry picked from commit 4b091cfc2a)
2017-02-27 12:19:28 +01:00
Axel Lin
d6e8e05edd stats: Remove superfluous /t in end of stats display
The debug message after the stats display looks odd because the /t in end of
stats display.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit 2685d742e8)
2017-02-27 12:19:08 +01:00
Dirk Ziegelmeier
0b299f96e9 Add CHANGELOG to lwIP HTML documentation
(cherry picked from commit ee3154999a)
2017-02-27 12:18:26 +01:00
Dirk Ziegelmeier
777d54f0e4 Retry 1 to fix bug #50064
Accidentally used the wrong destination HW addr

(cherry picked from commit 645ca84704)
2017-02-27 12:17:41 +01:00
Dirk Ziegelmeier
8c6ac8eb59 Optimize my last fix in etharp.c, I missed the variable declaration at the beginning of the function
(cherry picked from commit 7aaa888d1d)
2017-02-27 12:17:41 +01:00
Dirk Ziegelmeier
4fc3770278 Remove special ARP reply optimization from etharp.c
- Code duplication with etharp_raw()
- No great effect on perfomance
- May make reworking PBUF handling code more complicated (see bug #49914)
- The check for p->type == PBUF_REF is a strange special case, too
- Simon also voted to remove it

(cherry picked from commit 47bac3c11f)
2017-02-27 12:17:40 +01:00
Dirk Ziegelmeier
e53c84654e Fix bug #50064: Zero-copy RX: ARP reply fails with PBUF_REF
Kept the optimized version intact, see discussion in savannah bug tracker

(cherry picked from commit 199c38de29)
2017-02-27 12:17:40 +01:00
sg
d0b0cf983e fix compiling TCP unit tests with IPv6 enabled
(cherry picked from commit b198c877db)
2017-02-27 12:17:39 +01:00
Axel Lin
90d68b41df tcp_out: Use LWIP_MIN instead of open-coded for better readability
Make the intention of code more clear by using LWIP_MIN instead of open-coded.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit 141b5def46)
2017-02-27 12:16:17 +01:00
Axel Lin
e6756387b0 tcp_out: Fix comment for last_unsent->oversize_left and tcp_pcb.unsent_oversize
Both last_unsent->unsent_oversize and tcp_pcb.unsent_oversized fields are not
exist, fix the comments.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit 30aedfc3f7)
2017-02-27 12:16:17 +01:00
Dirk Ziegelmeier
4fe1436904 Add some parentheses for better code readability in tcp_in.c
(cherry picked from commit df8e404abd)
2017-02-27 12:16:16 +01:00
Dirk Ziegelmeier
1fdbda9700 Fix bug #50040: pbuf_alloc(..., 65534, PBUF_RAM) succeeds
Check for integer overflow when calculating memory allocation size
(cherry picked from commit 9898d406bc)
2017-02-27 12:16:16 +01:00
Dirk Ziegelmeier
fed15778dd Minor typo fix in tcp_out.c
(cherry picked from commit 0043bf78b6)
2017-02-27 12:16:16 +01:00
Axel Lin
bbe91e356f tcp_out: Fix oversize vs. space assertion test
oversize_used is always 0 at this point, should test oversize instead.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit e1598b0b11)
2017-02-27 12:16:15 +01:00
Dirk Ziegelmeier
0a73e0ff30 Set lwIP version to 2.0.2 in doxygen script
(cherry picked from commit 861dab5b22)
2017-02-27 12:16:15 +01:00
Dirk Ziegelmeier
7ba2633ef0 Minor code readability improvement in mqtt.c
(cherry picked from commit 5c58e25de5)
2017-02-27 12:14:46 +01:00
Dirk Ziegelmeier
d860dd7655 Minor correction to last patch: Avoid #including socket.h in api_msg.c
(cherry picked from commit 2b1ebda6f1)
2017-02-27 12:13:27 +01:00
Knut Andre Tidemann
2694486309 lwip: fix broken default ICMPv6 handling of checksums.
ICMPv6 should always have checksum generated for it as per RFC 3542
chapter 3.1.

(cherry picked from commit 5e9df2c698)
2017-02-27 12:13:26 +01:00
Dirk Ziegelmeier
cb97e27120 MQTT: Add check that WILL topic length must be > 0
(cherry picked from commit 52f448978f)
2017-02-27 12:09:49 +01:00
Dirk Ziegelmeier
890c5982a1 MQTT: Fix possible bug in connect message generation that WILL flag can be set without appending a will message
The boolean condition of setting the WILL flag differs from that of appending the will message
Found by Axel Lin
(I fixed it the same way as Axel suggested, but I wanted a different commit message)
(cherry picked from commit 6d5ddb7139)
2017-02-27 12:09:49 +01:00
Axel Lin
4deaebae44 mqtt: Slightly improve mqtt_create_request
Mainly for better readability, also save NULL test while iterating the for loop.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit a2915b7142)
2017-02-27 12:09:49 +01:00
Axel Lin
5fe195c3d3 mqtt: Prevent NULL pointer dereference before assertion checking
Signed-off-by: Axel Lin <axel.lin@ingics.com>
(cherry picked from commit 7faa4bcbe2)
2017-02-27 12:08:55 +01:00
Dirk Ziegelmeier
e5071daf45 Add MQTT to CHANGELOG (too late for 2.0.1 release...) 2017-01-10 10:42:25 +01:00
Dirk Ziegelmeier
980b219c28 Put 2.0.1 version tag in UPGRADING document 2017-01-10 10:42:23 +01:00
Erik Ekman
76b4365aaa Remove duplicate netif_dhcp_data() macro
Fix compilation of unit tests
2017-01-10 10:42:22 +01:00
Dirk Ziegelmeier
a5a4830b16 Set lwIP version to 2.0.1 RELEASE 2017-01-05 15:02:10 +01:00
Dirk Ziegelmeier
1a2a9a4e96 Merge branch 'master' into STABLE-2_0_0
# Conflicts:
#	src/include/lwip/init.h
2017-01-05 15:01:08 +01:00
Dirk Ziegelmeier
3a20ae3830 Add missing #include in netdb.c for atoi() 2017-01-05 08:55:12 +01:00
Dirk Ziegelmeier
0ffaccaec3 Add missing #include in httpd.c for atoi() 2017-01-05 08:53:26 +01:00
Dirk Ziegelmeier
e94c9ffa70 Fix warning about bad cast in pbuf_skip() 2017-01-05 08:14:39 +01:00
Dirk Ziegelmeier
72316bdb5b Move macros to access DHCP and AUTOIP data to headers, users may want to access the members 2017-01-05 08:09:00 +01:00
Dirk Ziegelmeier
803a711e6a Fix warning that local variable may be used uninitialized in mem.c 2017-01-05 08:07:41 +01:00
sg
8760fb677f fixed warnings in mdns unit tests 2017-01-04 15:25:52 +01:00
Erik Ekman
d2631e6a53 mqtt: Fix pedantic enum warning
src/apps/mqtt/mqtt.c:81:17: error: comma at end of enumerator list [-Werror=pedantic]
2017-01-04 00:24:00 +01:00
Dirk Ziegelmeier
4059748b47 I was not satisfied with the previous debugging options structure. Improve it again. 2017-01-02 19:50:46 +01:00
Dirk Ziegelmeier
644a21b8a5 Improve debugging options documentation 2017-01-02 19:32:56 +01:00
Dirk Ziegelmeier
a3876314b7 Add debugging options to documentation 2017-01-02 19:25:23 +01:00
Dirk Ziegelmeier
e3c2b8a339 Add note about high resource-consumption in LWIP_PLATFORM_DIAG and LWIP_PLATFORM_ASSERT default implementations 2017-01-02 19:06:33 +01:00
Dirk Ziegelmeier
e12bb2a4eb Fix comma at end of enum list in mqtt.h 2017-01-01 20:26:28 +01:00
Dirk Ziegelmeier
2096f1a657 Fix C++ style comment in mqtt.c 2017-01-01 20:23:11 +01:00
Axel Lin
1f3c18fcbe tcp: Make tcp_listen_with_backlog_and_err return NULL if the address/port is already used
The caller of tcp_listen_with_backlog_and_err() usually check if the return
pcb is NULL before checking the err reason. I think the commit adding
tcp_listen_with_backlog_and_err() accidently change the behavior, Fix it.

Fixes: 98fc82fa71 ("added function tcp_listen_with_backlog_and_err() to get the error reason when listening fails")
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2017-01-01 19:53:51 +01:00
Axel Lin
edfeab7932 mqtt: Trivial coding style fix
Add proper blank for if/for/while statements.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2017-01-01 19:20:24 +01:00
Dirk Ziegelmeier
b8bc7b7c71 arch.h: Add #includes necessary for default implentation of LWIP_PLATFORM_DIAG and LWIP_PLATFORM_ASSERT 2017-01-01 12:40:23 +01:00
Dirk Ziegelmeier
f874d15185 Add #include <string.h> in snmp_netconn.c because memset() is used 2017-01-01 12:38:34 +01:00
Dirk Ziegelmeier
ee034bd811 Document PACK_STRUCT_USE_INCLUDES #define 2017-01-01 12:31:02 +01:00
sg
a2a16d4193 nd6 rdnss: fixed dual-stack compilation 2016-12-31 15:51:59 +01:00
sg
98fc82fa71 added function tcp_listen_with_backlog_and_err() to get the error reason when listening fails (bug #49861) 2016-12-31 15:36:31 +01:00
Dirk Ziegelmeier
1884c7e83f Fix TCP unit tests after changes from "Add hook for TCP Initial Sequence Number generation" commit
(pcb->lastack and friends are not initialized during allocation any more, but by connect() / bind() call)
2016-12-31 11:46:27 +01:00
Dirk Ziegelmeier
1466b7ac61 Several mqtt documentation fixes found by clang 2016-12-29 09:44:07 +01:00
Dirk Ziegelmeier
748e2e925b Create documentation section "porting" and move it under lwIP section (instead of infrastructure) 2016-12-29 09:29:24 +01:00
Dirk Ziegelmeier
1fd69ddee9 Minor documentation update in def.c 2016-12-29 09:28:45 +01:00
Dirk Ziegelmeier
3a8368ef04 Provide struct packing macros on GCC/clang out of the box 2016-12-29 09:28:28 +01:00
Dirk Ziegelmeier
c1258e5c72 Compile fix in lwip/arch.h "extra tokens at end of #ifndef directive" 2016-12-29 09:05:52 +01:00
Dirk Ziegelmeier
211a71cf11 Minor documentation update in lwip/arch.h 2016-12-28 21:52:10 +01:00
Dirk Ziegelmeier
55199fc62c More documentation updates in lwip/arch.h 2016-12-28 10:14:36 +01:00
Dirk Ziegelmeier
45ad6f2e61 Minor documentation updates in lwip/arch.h 2016-12-28 09:53:11 +01:00
Dirk Ziegelmeier
df365adf9a Trivial typo fix in arch.h docs 2016-12-26 10:53:41 +01:00
Axel Lin
7b40d1eb6f doc: mqtt_client: Update example code after adding port parameter to mqtt_client_connect()
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-24 15:10:56 +01:00
Dirk Ziegelmeier
c1d16c61eb Forgot documentation on MQTT port #define 2016-12-24 12:06:53 +01:00
Dirk Ziegelmeier
83b1c397a0 Add #define with default MQTT port for convenience 2016-12-24 12:05:27 +01:00
Axel Lin
bfa0358a52 mqtt: Allow setting server port to connect
This is a mqtt client, so it does not make sense to determinate the server port
at compile time. Update mqtt_client_connect() function to allow setting server
port.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-23 09:52:31 +01:00
Dirk Ziegelmeier
2e4b368c8c Revert "Fix bug #49914: lwip_sendmsg uses PBUF_REF pbufs"
This reverts commit 4e34851c57.
2016-12-23 09:51:26 +01:00
Dirk Ziegelmeier
4e34851c57 Fix bug #49914: lwip_sendmsg uses PBUF_REF pbufs
Use PBUF_RAM and create private copy of the data
2016-12-22 21:19:53 +01:00
Dirk Ziegelmeier
3a557baedd Move a few MQTT options from mqtt.c to mqtt_opts.h 2016-12-21 09:42:25 +01:00
Dirk Ziegelmeier
6e219b6b11 Change signature of mqtt_client_connect() to take an IP addr instead of a string 2016-12-21 09:36:28 +01:00
Dirk Ziegelmeier
ec1450bac4 Add mqtt documentation from Erik Anderson, rev 4b84fff 2016-12-21 09:29:47 +01:00
Axel Lin
5be91de56c mqtt: Trivial error message fix
Fix trivial copy-paste mistake.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-21 08:54:57 +01:00
David van Moolenbroek
24fa1c457e opt.h: provide some hints regarding MLD settings 2016-12-20 22:28:11 +01:00
David van Moolenbroek
71810d0415 ipv6: adjust MLD membership on address state changes
If MLD support is enabled, each locally assigned IPv6 address in the
appropriate state must be a member of the solicited-node multicast
group corresponding to that address.  Ensure that this is always the
case by (re-)deciding on the membership upon every address state
change.  By doing so, this patch enforces that user-initiated state
changes to addresses (e.g., deletion) never cause a desynchronization
with the corresponding solicited-node multicast group membership,
thereby making such user-initiated state changes simpler and safer.
2016-12-20 22:28:02 +01:00
Axel Lin
d5bc856f45 mqtt: Check conn_state before create request for sub_unsub
This also avoid a request leak in client->conn_state == TCP_DISCONNECTED error
path.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-20 19:45:31 +01:00
Dirk Ziegelmeier
876720593b Update .gitignore once more for fuzz test 2016-12-20 14:25:46 +01:00
Dirk Ziegelmeier
dd96c71253 Fix a few -Wconversion warnings (there are many more to do) 2016-12-20 14:22:51 +01:00
Thomas Mueller
be57134810 Fixed bug #49895: Incorrect configuration detection in lwip/dns.h
Signed-off-by: goldsimon <goldsimon@gmx.de>
2016-12-20 14:21:26 +01:00
Dirk Ziegelmeier
16b895b466 Undo removal of mqtt_publish() from documentation in Simon's last commit (guess it was by accident) 2016-12-20 10:48:19 +01:00
Dirk Ziegelmeier
dcb761637d Minor documentation fix in MQTT 2016-12-20 10:42:56 +01:00
Axel Lin
02f4610b1c mqtt: Use LWIP_ARRAYSIZE to replace hardcoded value
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-20 10:36:42 +01:00
goldsimon
b6a131edfb mqtt: fix C usage (declaration after statement), fix casting to smaller type 2016-12-20 10:27:43 +01:00
Dirk Ziegelmeier
12bc2c0425 MQTT cleanups:
- create mqtt_opts.h file and move options in there
- documentation cleanups
2016-12-20 10:08:50 +01:00
Dirk Ziegelmeier
14e36866f5 Some cleanups in MQTT client
Integrate in documentation
Compile fixes, mostly: Variables must be declared before any statement in a function
2016-12-20 09:41:21 +01:00
Dirk Ziegelmeier
1e82465766 task #14281: Add MQTT client
Thanks to Erik Andersen
Taken from https://github.com/erian747/, branch mqtt, rev 5d59470
2016-12-20 09:16:21 +01:00
goldsimon
fb07d47b82 more LWIP_NOASSERT fixes 2016-12-19 10:34:49 +01:00
goldsimon
c71733252c Fix compiling with LWIP_NOASSERT (and debug/error disabled, too) 2016-12-19 10:29:16 +01:00
Dirk Ziegelmeier
e0c0ba7e1b Fix compile with LWIP_NOASSERT
Pointed out by Nirav Desai
2016-12-19 10:11:23 +01:00
Dirk Ziegelmeier
7f319f5ec5 Fix compile of test_tcp.c unit test after introduction of tcp_next_iss hook 2016-12-18 21:46:49 +01:00
Dirk Ziegelmeier
c21763f6cb Minor code cleanup api_lib.c 2016-12-18 21:31:14 +01:00
Axel Lin
f488c5b7bc igmp: Fix optimized code for igmp_remove_group
The code in the for loop checks tmp_group->next == group, so current code
actually checks from the 3rd entry in the linked groups list. Fix it.

Fixes: 5c1dd6a4c6 ("Optimization in igmp_remove_group() pointed out by Axel Lin")
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-17 22:01:30 +01:00
Dirk Ziegelmeier
5c1dd6a4c6 Optimization in igmp_remove_group() pointed out by Axel Lin
No need to handle special case "first in list" since this is always the allsystems group that shall not be removed
2016-12-17 15:06:33 +01:00
Dirk Ziegelmeier
102a50fa96 Fix bug #39145: IGMP membership report for 224.0.0.1
Ensure allsystems group is always first in linked list
2016-12-17 13:36:24 +01:00
Dirk Ziegelmeier
bb8088d498 Minor cleanup of FUZZ test Makefile 2016-12-17 10:09:15 +01:00
Dirk Ziegelmeier
11780f037b Fixup Makefile of FUZZ test after moving to main lwIP rep 2016-12-17 10:05:49 +01:00
Joel Cunningham
cceea73c3f bug #49631: handle zero-window probe and refused_data
This commit adds support for responding to a zero-window probe when
the refused_data pointer is set

A zero-window probe is a data segment received when rcv_ann_wnd
is 0. This corrects a standards violation where LwIP would not
respond to a zero-window probe with its current ACK value (RCV.NXT)
when it has refused data, thus leading to the probing TCP closing
out the connection
2016-12-16 09:37:54 -06:00
Thomas Mueller
fcd2daf57c fixed race condition in return value of netconn_gethostbyname() (and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo())
Signed-off-by: sg <goldsimon@gmx.de>
2016-12-16 15:44:00 +01:00
Dirk Ziegelmeier
b5f51dbd0c ND6: Don't misuse ip6_current_dest_addr() to create an aligned copy of an IPv6 address
We never know what side effect in application code this could trigger...
2016-12-16 08:51:06 +01:00
sg
d9f461e4e4 Fixed #49848 (Non-blocking socket emit a sock error while read return EWOULDBLOCK) especially for EWOULDBLOCK (added task #14275 for the general problem) 2016-12-15 22:32:46 +01:00
sg
c13a43e5c8 added note about afl-fuzz requiring linux 2016-12-15 21:42:46 +01:00
sg
844c201702 added fuzz tests (moved from contrib/ports/unix/fuzz to get them to a more prominent place, even if afl-fuzz still needs *nix to run) 2016-12-15 21:39:46 +01:00
sg
62e340067e LWIP_HOOK_TCP_ISN: added CHANGELOG/fixed comment 2016-12-15 21:08:12 +01:00
David van Moolenbroek
a8b986bbb6 Add hook for TCP Initial Sequence Number generation
lwIP produces a TCP Initial Sequence Number (ISN) for each new TCP
connection. The current algorithm is simple and predictable however.
The result is that lwIP TCP connections may be the target of TCP
spoofing attacks.  The problem of such attacks is well known, and a
recommended ISN generation algorithm is standardized in RFC 6528.
This algorithm requires a high-resolution timer and cryptographic
hashing function, though.  The implementation (or best-effort
approximation) of both of these aspects is well beyond the scope of
lwIP itself.

For that reason, this patch adds LWIP_HOOK_TCP_ISN, a hook that
allows each platform to implement its own ISN generation using
locally available means.  The hook provides full flexibility, in
that the hook may generate anything from a simple random number
(by being set to LWIP_RAND()) to a full RFC 6528 implementation.

Implementation note:

Users of the hook would typically declare the function prototype of
the hook function in arch/cc.h, as this is the last place where such
prototypes can be supplied.  However, at that point, the ip_addr_t
type has not yet been defined.  For that reason, this patch removes
the leading underscore from "struct _ip_addr", so that a prototype
of the hook function can use "struct ip_addr" instead of "ip_addr_t".

Signed-off-by: sg <goldsimon@gmx.de>
2016-12-15 20:18:08 +01:00
goldsimon
da15132aa0 Make nd6_new_router() handle already existing routers (this is a special case for 2 netifs on the same subnet - e.g. wifi and cable) see bug #46506 2016-12-15 09:25:44 +01:00
Axel Lin
e3925cc359 nd6: Fix build error if LWIP_ND6_RDNSS_MAX_DNS_SERVERS == 0
Fix below build error when LWIP_ND6_RDNSS_MAX_DNS_SERVERS == 0
../../../../lwip/src/core/ipv6/nd6.c: In function ‘nd6_input’:
../../../../lwip/src/core/ipv6/nd6.c:400:10: error: unused variable ‘rdnss_server_idx’ [-Werror=unused-variable]
     u8_t rdnss_server_idx = 0;
          ^~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
../Common.mk:93: recipe for target 'nd6.o' failed
make: *** [nd6.o] Error 1

Fixes: 6b1950ec24 ("nd6: add support for RDNSS option (as per RFC 6106)")
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-15 08:11:34 +01:00
sg
6b1950ec24 nd6: add support for RDNSS option (as per RFC 6106) 2016-12-14 22:12:14 +01:00
sg
4e3cf61571 opt.h: added LWIP_DHCP_MAX_DNS_SERVERS to configure the maximum number of DNS servers configured from dhcp.c(v4) (if any; guarded with LWIP_DNS) 2016-12-14 22:04:08 +01:00
sg
53b9f2a5bd dhcp: covert DHCP_OPTION_IDX_* from defines to enum (mainly to ease offset calculation) 2016-12-14 21:56:39 +01:00
David van Moolenbroek
cd5dfa2bc5 nd6: minor 'static' consistency fix 2016-12-14 21:25:55 +01:00
sg
bd1defc1d8 added forgoten new file nd6_priv.h :-( 2016-12-14 21:24:48 +01:00
sg
281ef5d094 minor: fixed errors in some defined __DOXYGEN__ guards 2016-12-14 21:18:50 +01:00
sg
e8461f9994 minor: corrected include guard name in tcp_priv.h 2016-12-14 21:05:22 +01:00
sg
60cd25c6a1 Moved nd6 implementation details to new file nd6_priv.h (possible after David's cleanups) 2016-12-14 21:04:53 +01:00
sg
4c16ea920c Minor: nd6_packet_send_check() -> nd6_get_next_hop_addr_or_queue() (too long, but a little more self-explaining); cosmetics... 2016-12-14 20:52:44 +01:00
David van Moolenbroek
69a7039f75 nd6: centralize link-local packet send decision
Previously, ethip6 and lowpan6 each had their own copy of code that
used internal nd6 data structures to decide whether to send a packet
on the local link right away, or queue it while nd6 performed local
address resolution.  This patch moves that code into nd6, thereby
eliminating all remaining cases of external access to internal nd6
data structures, as well as the need to expose two specific nd6
functions.

As a side effect, the patch effectively fixes two bugs in the lowpan6
code that were already fixed in the ethip6 code.
2016-12-14 20:19:50 +01:00
David van Moolenbroek
06ff89cbe4 nd6: use default_router_list internally only
This patch rearranges the code division between nd6.c and ip6.c such
that the latter does not need to access ND6-internal data structures
(specifically, "default_router_list") directly anymore.
2016-12-14 20:16:38 +01:00
David van Moolenbroek
cee59ba8cd nd6: add nd6_clear_destination_cache() function
The new function, while currently not used internally, allows external
code to clear the ND destination cache in the case that it may have
become inconsistent with the current situation, for example as the
result of a change of locally assigned addresses, or a change in
routing tables implemented through the LWIP_HOOK_ND6_GET_GW hook.
2016-12-14 20:12:40 +01:00
goldsimon
d4fad5929c nd6_input(): allow using NA without lladdr_opt for DAD 2016-12-14 13:11:13 +01:00
goldsimon
1a53c106e1 CHANGELOG: added LWIP_HOOK_ND6_GET_GW() 2016-12-14 08:42:11 +01:00
David van Moolenbroek
7d119fd86b nd6: add LWIP_HOOK_ND6_GET_GW hook 2016-12-14 08:36:57 +01:00
goldsimon
74a5537e15 Revert "Added LWIP_HOOK_ETHIP6_GET_GW()"
This reverts commit 86b01e4f29.
2016-12-14 08:36:47 +01:00
goldsimon
afb21603dc Add a check for correct implementation of LWIP_CONST_CAST() to lwip_init() 2016-12-14 08:31:09 +01:00
David van Moolenbroek
002e077dbd ethip6: forward correct error code
On failure, nd6_get_next_hop_entry() returns an ERR_ type negative
error code.  ethip6_output() erroneously assumed that that error would
always be ERR_MEM, even though it may also be ERR_RTE in practice.
With this patch, ethip6_output() simply forwards the returned error.
2016-12-14 08:29:36 +01:00
sg
9d199a6d72 netif_create_ip6_linklocal_address(): use macros to assign address state to ensure callbacks are triggered; netif_add_ip6_address(): only overwrite invalid addresses, not tentative addresses 2016-12-13 21:54:49 +01:00
Pradip De
86b01e4f29 Added LWIP_HOOK_ETHIP6_GET_GW()
Signed-off-by: sg <goldsimon@gmx.de>
2016-12-13 21:53:07 +01:00
Dirk Ziegelmeier
1c184da615 Update changelog for LWIP_NETIF_TX_SINGLE_PBUF 2016-12-13 18:48:26 +01:00
Dirk Ziegelmeier
e5f9f187ad Continue to fix incorrect casts via size_t for some platforms
Now also for casts:
- to remove alignment warnings
- casts between pointers and ints
2016-12-12 10:17:33 +01:00
Dirk Ziegelmeier
f2a5aa2866 Fix bug #49827: wrong cast to size_t on 16-bit x86 architecture
I hope I caught all of them.
TODO: Same for casts to get rid of alignment warnings, these are also casts via size_t
2016-12-12 10:07:00 +01:00
Dirk Ziegelmeier
7a1b38db6e Minor: Save an #ifdef in ip4_frag.c 2016-12-09 21:26:53 +01:00
Dirk Ziegelmeier
26e02e84a6 Fix bug #48963: ip6_frag does not support LWIP_NETIF_TX_SINGLE_PBUF
Implemented.
2016-12-09 21:26:21 +01:00
Dirk Ziegelmeier
8347d3b623 Try to fix compile warning with GCC under Linux ("large integer implicitly truncated to unsigned type") 2016-12-09 19:56:29 +01:00
Sylvain Rochet
a83c4e0897 PPP: fix build warning on wrong cast from void* to unsigned long
ppp/utils.c: In function 'ppp_vslprintf':
ppp/utils.c:251:12: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
     val = (unsigned long) va_arg(args, void *);
     ^

This is because a void* type is casted into an unsigned long type,
which obviously isn't correct on LLP64 systems such as Windows.

Actually, we are not using %p, thus we remove %p support completely
instead of trying to fix the issue in unused code.
2016-12-09 14:25:47 +01:00
goldsimon
ac4d994249 mdns.c: use group initializer constants from prot/dns.h 2016-12-09 13:10:12 +01:00
goldsimon
f308694dd4 Revert "mdns.c: use constants from dns.h/.c"
This reverts commit 0e883bbbc5.
2016-12-09 13:08:00 +01:00
goldsimon
0e883bbbc5 mdns.c: use constants from dns.h/.c 2016-12-09 12:49:49 +01:00
goldsimon
5774fdfe75 dns: added one-shot multicast DNS queries 2016-12-09 09:20:46 +01:00
Dirk Ziegelmeier
85817e7611 Minor documentation update about IP_ADDR_ANY 2016-12-08 16:56:19 +01:00
Dirk Ziegelmeier
a2ad9d36ca Improve documentation: Refer to compiler/platform abstraction in NO_SYS mode description 2016-12-08 15:25:38 +01:00
Dirk Ziegelmeier
33bdf9fa76 Doxygen: Fix project description text 2016-12-08 13:38:17 +01:00
Dirk Ziegelmeier
55fd567a84 Adapt doxygen docs version number 2016-12-08 13:37:01 +01:00
Dirk Ziegelmeier
b359b8c3e0 Minor documentation improvement 2016-12-08 13:35:34 +01:00
Dirk Ziegelmeier
bb6df52ed5 Fix doxygen parsing in my last commit 2016-12-08 12:47:30 +01:00
Dirk Ziegelmeier
8a9ab9968c Improve documentation: add compiler abstraction macros to doxygen docs 2016-12-08 12:45:21 +01:00
Dirk Ziegelmeier
a420d2530f arch.h: Add hint for struct packing #defines on GCC/clang 2016-12-08 11:13:51 +01:00
Dirk Ziegelmeier
89cb7b7aa1 Try to remove #include <stdlib.h> from many files. Does not seem necessary any more and might cause problems when porting lwIP. 2016-12-08 11:05:01 +01:00
goldsimon
9c3bbcf4e6 removed old disabled code 2016-12-08 10:24:56 +01:00
Dirk Ziegelmeier
f446194c8a pppos.c: Use arch.h to get size_t instead of including stddef.h 2016-12-07 22:29:24 +01:00
Dirk Ziegelmeier
1dd563a0ae arch.h: Implement possibility to provide own header for size_t, default is stddef.h 2016-12-07 22:27:57 +01:00
Dirk Ziegelmeier
aae0fc4908 Use new IPv6 init macro in netif.c 2016-12-07 22:19:37 +01:00
Dirk Ziegelmeier
5bb83301dd Add macro to init an IPv6 address with U32 in host byte order 2016-12-07 22:19:16 +01:00
Dirk Ziegelmeier
0ca82df062 Cleanup byte order handling a bit.
- Create LWIP_MAKEU32(a,b,c,d) to create an U32 value from bytes
- Use PP_HTONL() in some macros to emphasize network byte order conversion
2016-12-07 20:18:58 +01:00
goldsimon
ff3656f4f5 Added improved macros for ip address initialization: IPADDR4_INIT_BYTES(), IPADDR6_INIT_HOST() and IP4_ADDR_MAKEU32() 2016-12-07 13:06:07 +01:00
goldsimon
b31b0c8148 remove bogus LWIP_MAKE_U16() define and use PP_NTOHS() in ip4.c instead 2016-12-07 12:44:57 +01:00
goldsimon
c87855423c DNS: added compile-time check for some defines to fit into an u8_t (bug #49658) 2016-12-07 09:09:45 +01:00
Dirk Ziegelmeier
e00a131160 Fix bug #49778: sntp_stop does not cancel all timers
Patch by Ari Suutari
2016-12-06 20:29:12 +01:00
Dirk Ziegelmeier
cb29a49a64 Update CHANGELOG 2016-12-06 11:39:03 +01:00
Axel Lin
795acf020e lwiperf: Simplify #if LWIPERF_CHECK_RX_DATA guard
The variable i is equal to q->len after exit the for loop.
Check the received data should not change the logic of update packet_idx.
So let's simplify the code a bit.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-06 11:36:25 +01:00
Dirk Ziegelmeier
cc25c2634b Cleanup: move struct ip6_addr_packed and ip6_addr_p_t type to prot/ip6.h - these types are used in prot/ip6.h and prot/mld6.h 2016-12-06 09:36:36 +01:00
Dirk Ziegelmeier
1687721600 Fix compile when IPv4 is disabled 2016-12-05 22:01:58 +01:00
Dirk Ziegelmeier
a6bc422729 Move declaration of struct ip4_addr_packed and ip4_addr_p_t to prot/ip4.h
The types are used in structs declared in ip4.h.
2016-12-05 21:53:43 +01:00
Axel Lin
92183bb354 icmp: Increment mib2.icmpintimeexcds counter if got ICMP_TE
Increment mib2.icmpintimeexcds rather than mib2.icmpindestunreachs if got ICMP_TE.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-12-05 12:30:09 +01:00
Sylvain Rochet
bcaf2f08aa PPP, PPPoS: fix memory leak when disconnecting if there are remaining input bytes
Art says:
  pppos_input() can call ppp_input() which can call pppos_disconnect() to
  disconnect the interface.  However, it will continue to read in
  characters and allocate a pbuf from the PBUF_POOL and keep it in
  pppos->in_head and in_tail. When a re-connect happens and pppos_connect()
  is called, this pppos->in_head and in_tail are zeroed, hence a memory
  leak. (This happens with PPP_INPROC_IRQ_SAFE not defined.)

  A fix would be inside pppos_input() to break out of the loop inputting
  characters after calling ppp_input() if pppos->open == 0.  Note that
  the loop is not even entered if pppos->open == 0.

          ppp_input(ppp, inp);
          if(pppos->open == 0) //get out if they disconnected
            break;

Fix it in a similar way which doesn't add new code by moving the
existing pppos->open check inside the byte loop.
2016-12-03 16:12:51 +01:00
Dirk Ziegelmeier
4bbed75cc4 Minor code layout cleanup in err.c and errno.h 2016-12-01 08:55:01 +01:00
Joel Cunningham
7d0aeaf539 Doc: correct minor mis-spelling in sys_arch.txt
This corrects a minor mis-spelling where "by" was mis-spelled as "ny"
2016-11-30 10:28:38 -06:00
Joel Cunningham
f28e63b2a3 Add netifapi macros for set link up/down
This commit extends the netifapi macros to support netif_set_link_up
and netif_set_link_down
2016-11-30 08:49:23 -06:00
Joel Cunningham
7f48289fcd Increment ip.drop when dropping due to NULL netif
This commit increments the ip.drop statistic when an IP packet is
dropped due to no matching netif found and forwarding is disabled

This adds parity to the other places where mib2.ipinaddrerrors and
mib2.ipindiscards are incremented which also increment ip.drop
2016-11-30 08:49:22 -06:00
Axel Lin
12e35c4c12 mdns: Fix assertion message in mdns_resp_add_service_txtitem()
So we know which function emits the assertion.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-11-30 11:36:05 +01:00
Dirk Ziegelmeier
182d7c138a Add #include <stddef.h> to a central place (arch.h) instead of #including it in several other files throughout lwip since size_t is needed in many places
See http://lwip.100.n7.nabble.com/Issue-in-arch-h-for-lwIP-2-0-0-td27948.html
2016-11-30 07:43:59 +01:00
Dirk Ziegelmeier
47fd67a35c Remove TODO comments and one check from sockets.c indicating IPV6_V6ONLY socket option handling does not work 2016-11-28 15:56:59 +01:00
goldsimon
b934c3f471 fixed bug #49726: setsockopt() set TCP_NODELAY TCP_KEEPALIVE ... with a listen state TCP will crash 2016-11-28 15:50:59 +01:00
goldsimon
2a882b6387 minor: fixed indent 2016-11-28 12:54:17 +01:00
goldsimon
ca9342c549 fixed bug #49725 (send-timeout: netwonn_write() can return ERR_OK without all bytes being written) 2016-11-28 12:51:45 +01:00
goldsimon
6f1304e03e patch by Ambroz Bizjak: fixed bug #49717 (window size in received SYN and SYN-ACK assumed scaled) 2016-11-28 10:27:21 +01:00
Axel Lin
cac3dc8a46 netif: Trivial indent fix
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-11-28 10:24:23 +01:00
Dirk Ziegelmeier
aea872431c Fix naming of some inet_addr_* macros in inet.h
From inet4_addr_* to inet_addr_* - inet_addr is a "known word", don't change it
2016-11-25 22:13:12 +01:00
Axel Lin
1d4cbe768d netif: Add proper lock protect for accessing netif->loop_first
All the reset part of the code accessing netif->loop_first has lock protection,
the only missing part is "while (netif->loop_first != NULL)".
Fix it by adding lock protect around the while loop.

Also convert the code to use while{} loop instead of do .. while{} loop,
then we can avoid NULL test for in pointer in each loop and reduce a level of indent.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2016-11-25 13:02:23 +01:00
goldsimon
0e07ed4b13 fixed bug #49676 (Possible endless loop when parsing dhcp options) & added unit test for that 2016-11-25 10:03:43 +01:00
Richard Sailer
2ed755764e doxygen/generate.sh: Add shebang line
This file had the x bit set.
But executing it produced an error, since it was
missing the "#!/bin/sh" line.

This patch adds the "#!/bin/sh" line and makes generate.sh directly executable.
2016-11-25 09:12:40 +01:00
goldsimon
f419231dc3 fixed typo in CHANGELOG 2016-11-24 11:31:46 +01:00
Ambroz Bizjak
8ba7363d11 Optimize passing contiguous nocopy buffers to tcp_write
While TCP_OVERSIZE works only when tcp_write() is used with
TCP_WRITE_FLAG_COPY, this new code achieves
similar benefits for the use case that the caller manages their own
send buffers and passes successive chunks of those to tcp_write()
without TCP_WRITE_FLAG_COPY.

In particular, if a buffer is passed to
tcp_write() that is adjacent in memory to the previously passed
buffer, it will be combined into the previous ROM pbuf reference
whenever possible, thus extending that ROM pbuf rather than allocating
a new ROM pbuf.

For the aforementioned use case, the advantages of this code are
twofold:
1) fewer ROM pbufs need to be allocated to send the same data, and,
2) the MAC layer gets outgoing TCP packets with shorter pbuf chains.

Original patch by Ambroz Bizjak <ambrop7@gmail.com>
Edited by David van Moolenbroek <david@minix3.org>
Signed-off-by: goldsimon <goldsimon@gmx.de>
2016-11-24 11:27:34 +01:00
goldsimon
4c8620e03b Added important post-2.0.0 changes to CHANGELOG to keep track of changes for future 2.0.1 release 2016-11-24 11:21:00 +01:00
goldsimon
eb1de78ce1 prepare CHANGELOG for post-2.0.0 2016-11-24 11:12:22 +01:00
Joel Cunningham
5030fa81a0 bug #49684, api_msg: treat non-blocking ERR_MEM as ERR_WOULDBLOCK
This corrects a case in lwip_netconn_do_writemore() where if a
non-blocking socket receives ERR_MEM in a call to tcp_write(), it would
return ERR_MEM, which would result in ENOMEM coming out of the socket
layer

This case can be gracefully handled by returning ERR_WOULDBLOCK since the
socket is already marked as no longer writable and sent_tcp/poll_tcp will
mark the socket as writable again based on available buffer space

This is very similiar to how ERR_MEM is resolved for blocking sockets
2016-11-23 15:03:43 -06:00
Dirk Ziegelmeier
0f87cb92b8 Add note about UDP multicast behavior fix to UPGRADING document 2016-11-23 13:10:16 +01:00
Dirk Ziegelmeier
09547832ba Fix bug #49662: UDP layer should filter incoming multicast datagrams against the bound IP address
Change lwIP UDP API to match socket behavior. Multicast traffic is now only received on a UDP PCB (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY.
2016-11-23 12:46:35 +01:00
Sylvain Rochet
8c3c96baf7 PPP, L2TP: fix PPPOL2TP_AUTH_SUPPORT == 0 support
Fix compiler warnings on unused parameters and a function signature
mismatch in PPPAPI.
2016-11-22 22:13:24 +01:00
sg
03a9aac157 dns_enqueue(): minor readability improvement: add local variable "age" to store result of subtraction 2016-11-22 21:34:12 +01:00
David van Moolenbroek
68ec20fffc ipv4/ipv6: restrict loopback-destined traffic
Generally speaking, packets with a loopback destination address -
127.0.0.1 for IPv4 and ::1 for IPv6 - should not be accepted on
non-loopback interfaces.  For IPv4, this is implied by RFC 1122
Sec. 3.2.1.3.  For IPv6, it is mandated by RFC 4291 Sec. 2.5.3.
Failure to perform this filtering may have security implications, as
applications that bind sockets to loopback addresses may not expect
that nodes on the local external network be able to produce traffic
that will arrive at such sockets.

With this patch, lwIP drops packets that are sent to a loopback
address but do not originate from the interface that has the loopback
address assigned to it.  This approach works regardless of whether it
is lwIP or the system using it that implements a loopback netif.  The
only exception that must be made is for configurations that enable
netif packet loopback but disable the lwIP loopback netif: in that
case, loopback packets are routed across non-loopback netifs and would
thus be lost by the new filter as well.

For IPv6, loopback-destined packets are also no longer forwarded; the
IPv4 forwarding code already had a check for that.

As a small performance improvement, the IPv6 link-local/loopback
address check is now performed only once per packet rather than
repeatedly for every candidate netif.
2016-11-22 20:51:36 +01:00
Dirk Ziegelmeier
4076b12ee9 Revert "Apply patch #9165: Allowing udp src port to be 0 in cases when we don't care about outgoing port"
This reverts commit 31b0237c50.
2016-11-22 14:35:45 +01:00
David van Moolenbroek
0034abfa45 Always check whether netif_default is NULL
In general, netif_default may be NULL, and various places in the code
already check for this case before attempting to dereference the
netif_default pointer.  Some places do not perform this check though,
and may cause null pointer dereferences if netif_default is not set.
This patch adds NULL checks to those places as well.
2016-11-21 10:16:28 +01:00
Dirk Ziegelmeier
31b0237c50 Apply patch #9165: Allowing udp src port to be 0 in cases when we don't care about outgoing port 2016-11-18 08:13:15 +01:00
Dirk Ziegelmeier
9366c0eaab I decided to keep the "complexity" of handling IPv6 mapped IPv4 addresses out of netconn API.
Only socket API understands this address type now.
2016-11-17 12:41:00 +01:00
Dirk Ziegelmeier
5d5eeca008 Once more: Try fix compile with clang 2016-11-17 09:23:57 +01:00
Dirk Ziegelmeier
4b7e0f50b7 Fix indent in api_lib.c 2016-11-17 09:14:29 +01:00
Dirk Ziegelmeier
44e430ebc2 Fix compile with MSVC 2010 and remove handling for IP6_ADDR_ANY in netconn_connect() - IP6_ADDR_ANY does not make sense in connect() 2016-11-17 09:12:38 +01:00
Dirk Ziegelmeier
180ba72a06 Dual-stack: Use IPv6 mapped IPv4 addresses in receive() and getaddr() only in socket API, not in netconn API.
It is better to present correct IP types in netconn API.
Netconn API now accepts IPv6 mapped IPv4 addresses as well as IPv6 and IPv4 in send(), bind() and connect(), but does NOT map IPv4 to IPv6 mapped IPv4 in getaddr() and receive() functions.
2016-11-17 08:51:07 +01:00
Dirk Ziegelmeier
792224ead0 Try to fix compile error with clang (found by Erik's Travis-CI) 2016-11-17 08:48:55 +01:00
Dirk Ziegelmeier
e8e853f2cb Move ICMP6 protocol constants to include/lwip/prot/icmp6 2016-11-16 23:49:44 +01:00
Dirk Ziegelmeier
80a24c0399 raw, udp, tcp connect() does NOT need to match exact IP type - when PCB is bound to IPADDR_ANY_TYPE, it is OK to connect to IPv4 or IPv6
This should finally implement task #14187: Dual Stack sendto with socket APIs
2016-11-16 23:39:43 +01:00
Dirk Ziegelmeier
d026a3954a Dual-stack fixes in raw/udp/tcp
bind() may change IP type when previous type is IPADDR_TYPE_ANY
connect() IP type must exactly match bind IP type
Use correct IPADDRx_ANY type when calling ip_route()
2016-11-16 23:30:19 +01:00
Dirk Ziegelmeier
1712b06a64 Work on dual-stack netconn
IPv6 netconns are created as IPADDR_TYPE_ANY raw/udp/tcp PCBs internally
bind, connect and sendto now accept IPv6 mapped IPv4 addresses or IPv4 addresses as argument
getaddr and receive functions now return IPv6 mapped IPv4 addresses instead of IPv4 addresses
This behavior is close to BSD socket API
2016-11-16 22:58:38 +01:00
Dirk Ziegelmeier
010f3550b6 Cleanup macro parameter names 2016-11-16 21:37:41 +01:00
Dirk Ziegelmeier
b70ddf7b54 Cleanup unmap_ipv6_mapped_ipv4() macro 2016-11-16 21:37:41 +01:00
Dirk Ziegelmeier
1dd97e7d53 sockets.c, lwip_sendto(): Remove check whether IP address matches socket type. Is checked in lower layers anyway. 2016-11-16 21:37:41 +01:00
Dirk Ziegelmeier
2f37dc0606 api_msg.c: Partly add support for IPv6 mapped IPv4 addresses
- lwip_netconn_do_getaddr(): Convert IPv4 addresses to IPv6 mapped IPv4 addresses
- lwip_netconn_do_send(): Support IPv6 mapped IPv4 addresses
- Not done: connect(), bind()
2016-11-16 21:37:41 +01:00
Dirk Ziegelmeier
c1eb6d8aa4 Minor: Add macros to map/unmap IPv6 mapped IPv4 addresses 2016-11-16 21:37:41 +01:00
Dirk Ziegelmeier
ad17f345e7 mdns: Use strlen to determine string length of strings contained in a struct - padding seems to be applied to these strings, and sizeof() returns the _padded_ size???
Found by compiling with CLANG with address sanitizer enabled
2016-11-16 21:01:15 +01:00
Dirk Ziegelmeier
ee7a2f346c inet.h: Consistently name some inet <-> ipaddr conversion macros
They operate on ip4_addr_t, not on ip_addr_t
This should be clearly visible in their names
2016-11-16 20:30:13 +01:00
Dirk Ziegelmeier
b99b7577fc memp.c: Only check for overflow/underflow if an element could be allocated
In other words: Don't dereference NULL pointers
2016-11-16 20:15:51 +01:00
Joel Cunningham
f79eabd24b bug #49533: start persist timer when unsent seg can't fit in window
This commit returns LwIP to previous behavior where if the next unsent
segment can't be sent due to the current send window, we start the
persist timer. This is done to engage window probing in the case that
the subsequent window update from the receiver is dropped, thus
preventing connection deadlock

This commit refines the previous logic to only target the following case:
 1) Next unsent segment doesn't fit within the send window (not
    congestion) and there is some room in the window
 2) Unacked queue is empty (otherwise data is inflight and the RTO timer
    will take care of any dropped window updates)

See commit d8f090a759 (which removed this
behavior) to reference the old logic. The old logic falsely started the
persit timer when the RTO timer was already running.
2016-11-16 09:12:47 -06:00
Roberto Barbieri Carrera
81a32e9b06 Fixed bug #49610: Sometimes, autoIP fails to reuse the same address
Signed-off-by: goldsimon <goldsimon@gmx.de>
2016-11-16 12:24:57 +01:00
Joel Cunningham
6dc3a2108a WND_SCALE: duplicate define check & doc cleanup
This commit cleans up a duplicate #if check for LWIP_WND_SCALE in init.c
which was already under #if LWIP_WND_SCALE

This commit also improves documentation for TCP_WND in the window scaling
case to communicate TCP_WND is always the calculated (scaled) window value,
not the value reported in the TCP header

Our developers were confused by having to set both the window and scaling
factor and only after studying the usage of TCP_WND throughout the code, was
it determined to be the calculated (scaled) window
2016-11-11 16:06:54 -06:00
Dirk Ziegelmeier
f965034366 Fix inconsistent return value in udp_sendto_if() - ERR_RTE should always be returned when there is no available route 2016-11-11 11:13:26 +01:00
Dirk Ziegelmeier
fdcd8f6faf Fix bug #49578: lwip_socket_drop_registered_memberships API may not work with LWIP_SOCKET_OFFSET 2016-11-11 11:13:25 +01:00
Erik Ekman
b90682dc8b Update email address
I am leaving Verisure at the end of the month.
2016-11-10 11:19:51 +01:00
Dirk Ziegelmeier
b9dc415178 master: Set version to 2.0.1 2016-11-10 09:59:05 +01:00
Dirk Ziegelmeier
216bf89491 Set version to 2.0.0 release 2016-11-10 09:46:31 +01:00
Dirk Ziegelmeier
a68eddbd47 Merge branch 'master' into STABLE-2_0_0 2016-11-10 09:44:33 +01:00
goldsimon
fd096a5769 Set LWIP_VERSION_RC to RC2 2016-08-03 09:12:23 +02:00
goldsimon
15b75555a6 Merge branch 'master' into STABLE-2_0_0 2016-08-03 08:59:09 +02:00
sg
33955c636d Set LWIP_VERSION_RC to RC1 2016-04-27 22:04:51 +02:00
115 changed files with 4632 additions and 1154 deletions

5
.gitignore vendored
View File

@@ -1,3 +1,5 @@
*.o
*.a
/doc/doxygen/output/html
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
@@ -11,3 +13,6 @@
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
/src/apps/snmp/LwipMibCompiler/*.suo
/test/fuzz/output
/test/fuzz/lwip_fuzz
/test/fuzz/.depend

146
CHANGELOG
View File

@@ -4,6 +4,152 @@ HISTORY
* [Enter new changes just after this line - do not remove this line]
(STABLE-2.0.2)
++ New features:
2017-02-10: Dirk Ziegelmeier
* Implement task #14367: Hooks need a better place to be defined:
We now have a #define for a header file name that is #included in every .c
file that provides hooks.
++ Bugfixes:
2017-03-08
* tcp: do not keep sending SYNs when getting ACKs
2017-03-08: Joel Cunningham
* tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476)
2017-03-01: Simon Goldschmidt
* httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved
is called nested from httpd_post_receive_data() (bug #50424)
2017-02-28: David van Moolenbroek/Simon Goldschmidt
* tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb
2017-02-17: Simon Goldschmidt
* dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325)
2017-02-16: Simon Goldschmidt
* LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274)
2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier
* For tiny targtes, LWIP_RAND is optional (fix compile time checks)
2017-02-10: Simon Goldschmidt
* tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying
to send FIN from tcp_fasttmr
2017-02-09: Simon Goldschmidt
* sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on
invalid/reused socket) by not allowing to reallocate a socket that has
"select_waiting != 0"
2017-02-09: Simon Goldschmidt
* httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs.
LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED)
2017-02-08: Dirk Ziegelmeier
* Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191:
"IPv4-mapped IPv6 address"
2017-02-08: Luc Revardel
* mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even
if last reporter)
2017-02-08: David van Moolenbroek
* ip6.c: Patch #9250: fix source substitution in ip6_output_if()
2017-02-08: Simon Goldschmidt
* tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value
in tcp_write error path)
2017-02-02: Dirk Ziegelmeier
* Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails
2017-01-18: Dirk Ziegelmeier
* Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests.
2017-01-15: Axel Lin, Dirk Ziegelmeier
* minor bug fixes in mqtt
2017-01-11: Knut Andre Tidemann
* sockets/netconn: fix broken default ICMPv6 handling of checksums
(STABLE-2.0.1)
++ New features:
2016-12-31: Simon Goldschmidt
* tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error
reason when listening fails (bug #49861)
2016-12-20: Erik Andersen
* Add MQTT client
2016-12-14: Jan Breuer:
* opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106)
2016-12-14: David van Moolenbroek
* opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW()
2016-12-09: Dirk Ziegelmeier
* ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF
2016-12-09: Simon Goldschmidt
* dns.c: added one-shot multicast DNS queries
2016-11-24: Ambroz Bizjak, David van Moolenbroek
* tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290)
2016-11-16: Dirk Ziegelmeier
* sockets.c: added support for IPv6 mapped IPv4 addresses
++ Bugfixes:
2016-12-16: Thomas Mueller
* api_lib.c: fixed race condition in return value of netconn_gethostbyname()
(and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo())
2016-12-15: David van Moolenbroek
* opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial
sequence numbers (see contrib/addons/tcp_isn for an example implementation)
2016-12-05: Dirk Ziegelmeier
* fixed compiling with IPv4 disabled (IPv6 only case)
2016-11-28: Simon Goldschmidt
* api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return
ERR_OK without all bytes being written)
2016-11-28: Ambroz Bizjak
* tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK
assumed scaled)
2016-11-25: Simon Goldschmidt
* dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options)
2016-11-23: Dirk Ziegelmeier
* udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB
(and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY
2016-11-16: Dirk Ziegelmeier
* *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API
2016-11-14: Joel Cunningham
* tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit
in window)
2016-11-16: Roberto Barbieri Carrera
* autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address)
2016-11-11: Dirk Ziegelmeier
* sockets.c: fixed bug #49578 (dropping multicast membership does not work
with LWIP_SOCKET_OFFSET)
(STABLE-2.0.0)
++ New features:
2016-07-27: Simon Goldschmidt

View File

@@ -8,7 +8,14 @@ with newer versions.
* [Enter new changes just after this line - do not remove this line]
* TODO
(2.0.1)
++ Application changes:
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
ip_current_netif() to the desired netif for every packet.
See bug #49662 for an explanation.
(2.0.0)

View File

@@ -1 +1,3 @@
#!/bin/sh
doxygen lwip.Doxyfile

View File

@@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "lwIP 2.0.0"
PROJECT_NAME = "lwIP"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "lwIP 2.0.0"
PROJECT_NUMBER = "2.0.2"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = Lightweight IP stack
PROJECT_BRIEF = "Lightweight IP stack"
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55

View File

@@ -26,6 +26,11 @@
* @verbinclude "UPGRADING"
*/
/**
* @page changelog Changelog
* @verbinclude "CHANGELOG"
*/
/**
* @page contrib How to contribute to lwIP
* @verbinclude "contrib.txt"
@@ -103,7 +108,8 @@
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
* context and put them into a queue which is processed from mainloop.\n
* Call sys_check_timeouts() periodically in the mainloop.\n
* Porting: implement all functions in @ref sys_time and @ref sys_prot.\n
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
* @ref compiler_abstraction.\n
* You can only use @ref callbackstyle_api in this mode.\n
* Sample code:\n
* @include NO_SYS_SampleCode.c

162
doc/mqtt_client.txt Normal file
View File

@@ -0,0 +1,162 @@
MQTT client for lwIP
Author: Erik Andersson
Details of the MQTT protocol can be found at:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
-----------------------------------------------------------------
1. Initial steps, reserve memory and make connection to server:
1.1: Provide storage
Static allocation:
mqtt_client_t static_client;
example_do_connect(&static_client);
Dynamic allocation:
mqtt_client_t *client = mqtt_client_new();
if(client != NULL) {
example_do_connect(&client);
}
1.2: Establish Connection with server
void example_do_connect(mqtt_client_t *client)
{
struct mqtt_connect_client_info_t ci;
err_t err;
/* Setup an empty client info structure */
memset(&ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "lwip_test";
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
/* For now just print the result code if something goes wrong
if(err != ERR_OK) {
printf("mqtt_connect return %d\n", err);
}
}
Connection to server can also be probed by calling mqtt_client_is_connected(client)
-----------------------------------------------------------------
2. Implementing the connection status callback
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
{
err_t err;
if(status == MQTT_CONNECT_ACCEPTED) {
printf("mqtt_connection_cb: Successfully connected\n");
/* Setup callback for incoming publish requests */
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
if(err != ERR_OK) {
printf("mqtt_subscribe return: %d\n", err);
}
} else {
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
/* Its more nice to be connected, so try to reconnect */
example_do_connect(client);
}
}
static void mqtt_sub_request_cb(void *arg, err_t result)
{
/* Just print the result code here for simplicity,
normal behaviour would be to take some action if subscribe fails like
notifying user, retry subscribe or disconnect from server */
printf("Subscribe result: %d\n", result);
}
-----------------------------------------------------------------
3. Implementing callbacks for incoming publish and data
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
Example here uses a global variable, better would be to use a member in arg
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
the topic string and use it in mqtt_incoming_data_cb
*/
static int inpub_id;
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
{
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
/* Decode topic string into a user defined reference */
if(strcmp(topic, "print_payload") == 0) {
inpub_id = 0;
} else if(topic[0] == 'A') {
/* All topics starting with 'A' might be handled at the same way */
inpub_id = 1;
} else {
/* For all other topics */
inpub_id = 2;
}
}
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
{
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
if(flags & MQTT_DATA_FLAG_LAST) {
/* Last fragment of payload received (or whole part if payload fits receive buffer
See MQTT_VAR_HEADER_BUFFER_LEN) */
/* Call function or do action depending on reference, in this case inpub_id */
if(inpub_id == 0) {
/* Don't trust the publisher, check zero termination */
if(data[len-1] == 0) {
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
}
} else if(inpub_id == 1) {
/* Call an 'A' function... */
} else {
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
}
} else {
/* Handle fragmented payload, store in buffer, write to file or whatever */
}
}
-----------------------------------------------------------------
4. Using outgoing publish
void example_publish(mqtt_client_t *client, void *arg)
{
const char *pub_payload= "PubSubHubLubJub";
err_t err;
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
u8_t retain = 0; /* No don't retain such crappy payload... */
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
if(err != ERR_OK) {
printf("Publish err: %d\n", err);
}
}
/* Called when publish is complete either with sucess or failure */
static void mqtt_pub_request_cb(void *arg, err_t result)
{
if(result != ERR_OK) {
printf("Publish result: %d\n", result);
}
}
-----------------------------------------------------------------
5. Disconnecting
Simply call mqtt_disconnect(client)

View File

@@ -29,7 +29,7 @@ in a mailbox is just a pointer, nothing more.
Semaphores are represented by the type "sys_sem_t" which is typedef'd
in the sys_arch.h file. Mailboxes are equivalently represented by the
type "sys_mbox_t". Mutexes are represented ny the type "sys_mutex_t".
type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t".
lwIP does not place any restrictions on how these types are represented
internally.

View File

@@ -167,6 +167,9 @@ 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
# LWIPAPPFILES: All LWIP APPs
LWIPAPPFILES=$(SNMPFILES) \
$(HTTPDFILES) \
@@ -174,4 +177,5 @@ LWIPAPPFILES=$(SNMPFILES) \
$(SNTPFILES) \
$(MDNSFILES) \
$(NETBIOSNSFILES) \
$(TFTPFILES)
$(TFTPFILES) \
$(MQTTFILES)

View File

@@ -254,10 +254,22 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
#if LWIP_IPV4
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
if (addr == NULL) {
addr = IP4_ADDR_ANY;
}
#endif /* LWIP_IPV4 */
#if LWIP_IPV4 && LWIP_IPV6
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
* and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind
*/
if ((netconn_get_ipv6only(conn) == 0) &&
ip_addr_cmp(addr, IP6_ADDR_ANY)) {
addr = IP_ANY_TYPE;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
API_MSG_VAR_ALLOC(msg);
API_MSG_VAR_REF(msg).conn = conn;
@@ -286,10 +298,12 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
#if LWIP_IPV4
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
if (addr == NULL) {
addr = IP4_ADDR_ANY;
}
#endif /* LWIP_IPV4 */
API_MSG_VAR_ALLOC(msg);
API_MSG_VAR_REF(msg).conn = conn;
@@ -376,7 +390,6 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
#if LWIP_TCP
void *accept_ptr;
struct netconn *newconn;
err_t err;
#if TCP_LISTEN_BACKLOG
API_MSG_VAR_DECLARE(msg);
#endif /* TCP_LISTEN_BACKLOG */
@@ -385,11 +398,10 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
*new_conn = NULL;
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
err = conn->last_err;
if (ERR_IS_FATAL(err)) {
if (ERR_IS_FATAL(conn->last_err)) {
/* don't recv on fatal errors: this might block the application task
waiting on acceptmbox forever! */
return err;
return conn->last_err;
}
if (!sys_mbox_valid(&conn->acceptmbox)) {
return ERR_CLSD;
@@ -465,7 +477,6 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
{
void *buf = NULL;
u16_t len;
err_t err;
#if LWIP_TCP
API_MSG_VAR_DECLARE(msg);
#if LWIP_MPU_COMPATIBLE
@@ -489,13 +500,12 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
#endif /* LWIP_TCP */
LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
err = conn->last_err;
if (ERR_IS_FATAL(err)) {
if (ERR_IS_FATAL(conn->last_err)) {
/* don't recv on fatal errors: this might block the application task
waiting on recvmbox forever! */
/* @todo: this does not allow us to fetch data that has been put into recvmbox
before the fatal error occurred - is that a problem? */
return err;
return conn->last_err;
}
#if LWIP_TCP
#if (LWIP_UDP || LWIP_RAW)
@@ -562,7 +572,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
#if (LWIP_UDP || LWIP_RAW)
{
LWIP_ASSERT("buf != NULL", buf != NULL);
len = netbuf_len((struct netbuf *)buf);
len = netbuf_len((struct netbuf*)buf);
}
#endif /* (LWIP_UDP || LWIP_RAW) */
@@ -697,6 +707,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
API_MSG_VAR_ALLOC(msg);
API_MSG_VAR_REF(msg).conn = conn;
API_MSG_VAR_REF(msg).msg.b = buf;
@@ -734,6 +745,11 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
return ERR_OK;
}
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
#if LWIP_SO_SNDTIMEO
if (conn->send_timeout != 0) {
dontblock = 1;
}
#endif /* LWIP_SO_SNDTIMEO */
if (dontblock && !bytes_written) {
/* This implies netconn_write() cannot be used for non-blocking send, since
it has no way to return the number of bytes written. */
@@ -761,11 +777,7 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
non-blocking version here. */
err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
if ((err == ERR_OK) && (bytes_written != NULL)) {
if (dontblock
#if LWIP_SO_SNDTIMEO
|| (conn->send_timeout != 0)
#endif /* LWIP_SO_SNDTIMEO */
) {
if (dontblock) {
/* nonblocking write: maybe the data has been sent partly */
*bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
} else {
@@ -869,6 +881,7 @@ netconn_join_leave_group(struct netconn *conn,
API_MSG_VAR_ALLOC(msg);
#if LWIP_IPV4
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
if (multiaddr == NULL) {
multiaddr = IP4_ADDR_ANY;
@@ -876,6 +889,7 @@ netconn_join_leave_group(struct netconn *conn,
if (netif_addr == NULL) {
netif_addr = IP4_ADDR_ANY;
}
#endif /* LWIP_IPV4 */
API_MSG_VAR_REF(msg).conn = conn;
API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
@@ -914,6 +928,7 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
sys_sem_t sem;
#endif /* LWIP_MPU_COMPATIBLE */
err_t err;
err_t cberr;
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
@@ -946,13 +961,13 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
}
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
if (err != ERR_OK) {
cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
if (cberr != ERR_OK) {
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
return err;
return cberr;
}
sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
#if !LWIP_NETCONN_SEM_PER_THREAD

View File

@@ -43,6 +43,7 @@
#include "lwip/priv/api_msg.h"
#include "lwip/ip.h"
#include "lwip/ip_addr.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/raw.h"
@@ -544,21 +545,37 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
static void
pcb_new(struct api_msg *msg)
{
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4;
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
#if LWIP_IPV6 && LWIP_IPV4
/* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */
if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) {
iptype = IPADDR_TYPE_ANY;
}
#endif
/* Allocate a PCB for this connection */
switch(NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto);
if (msg->conn->pcb.raw != NULL) {
#if LWIP_IPV6
/* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */
if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) {
msg->conn->pcb.raw->chksum_reqd = 1;
msg->conn->pcb.raw->chksum_offset = 2;
}
#endif /* LWIP_IPV6 */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
}
break;
#endif /* LWIP_RAW */
#if LWIP_UDP
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
msg->conn->pcb.udp = udp_new_ip_type(iptype);
if (msg->conn->pcb.udp != NULL) {
#if LWIP_UDPLITE
if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
@@ -574,7 +591,7 @@ pcb_new(struct api_msg *msg)
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
msg->conn->pcb.tcp = tcp_new_ip_type(iptype);
if (msg->conn->pcb.tcp != NULL) {
setup_tcp(msg->conn);
}
@@ -588,15 +605,6 @@ pcb_new(struct api_msg *msg)
if (msg->conn->pcb.ip == NULL) {
msg->err = ERR_MEM;
}
#if LWIP_IPV4 && LWIP_IPV6
else {
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
/* Convert IPv4 PCB manually to an IPv6 PCB */
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
}
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
}
/**
@@ -1113,37 +1121,20 @@ lwip_netconn_do_bind(void *m)
} else {
msg->err = ERR_VAL;
if (msg->conn->pcb.tcp != NULL) {
const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr);
#if LWIP_IPV4 && LWIP_IPV6
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
*/
if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) &&
(netconn_get_ipv6only(msg->conn) == 0)) {
/* change PCB type to IPADDR_TYPE_ANY */
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
/* bind to IPADDR_TYPE_ANY */
ipaddr = IP_ANY_TYPE;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
msg->err = raw_bind(msg->conn->pcb.raw, ipaddr);
msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
break;
#endif /* LWIP_RAW */
#if LWIP_UDP
case NETCONN_UDP:
msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port);
msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port);
msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
break;
#endif /* LWIP_TCP */
default:
@@ -1323,6 +1314,13 @@ lwip_netconn_do_listen(void *m)
/* connection is not closed, cannot listen */
msg->err = ERR_VAL;
} else {
err_t err;
u8_t backlog;
#if TCP_LISTEN_BACKLOG
backlog = msg->msg.lb.backlog;
#else /* TCP_LISTEN_BACKLOG */
backlog = TCP_DEFAULT_LISTEN_BACKLOG;
#endif /* TCP_LISTEN_BACKLOG */
#if LWIP_IPV4 && LWIP_IPV6
/* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
@@ -1335,15 +1333,11 @@ lwip_netconn_do_listen(void *m)
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if TCP_LISTEN_BACKLOG
lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
#else /* TCP_LISTEN_BACKLOG */
lpcb = tcp_listen(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err);
if (lpcb == NULL) {
/* in this case, the old pcb is still allocated */
msg->err = ERR_MEM;
msg->err = err;
} else {
/* delete the recvmbox and allocate the acceptmbox */
if (sys_mbox_valid(&msg->conn->recvmbox)) {
@@ -1400,7 +1394,7 @@ lwip_netconn_do_send(void *m)
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
if (ip_addr_isany(&msg->msg.b->addr)) {
if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
} else {
msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
@@ -1588,10 +1582,11 @@ err_mem:
write_finished = 1;
conn->current_msg->msg.w.len = 0;
}
} else if ((err == ERR_MEM) && !dontblock) {
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
we do NOT return to the application thread, since ERR_MEM is
only a temporary error! */
} else if (err == ERR_MEM) {
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called.
For blocking sockets, we do NOT return to the application
thread, since ERR_MEM is only a temporary error! Non-blocking
will remain non-writable until sent_tcp/poll_tcp is called */
/* tcp_write returned ERR_MEM, try tcp_output anyway */
err_t out_err = tcp_output(conn->pcb.tcp);
@@ -1602,6 +1597,11 @@ err_mem:
err = out_err;
write_finished = 1;
conn->current_msg->msg.w.len = 0;
} else if (dontblock) {
/* non-blocking write is done on ERR_MEM */
err = ERR_WOULDBLOCK;
write_finished = 1;
conn->current_msg->msg.w.len = 0;
}
} else {
/* On errors != ERR_MEM, we don't try writing any more but return
@@ -1710,6 +1710,7 @@ lwip_netconn_do_getaddr(void *m)
ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
msg->conn->pcb.ip->remote_ip);
}
msg->err = ERR_OK;
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
@@ -1783,25 +1784,28 @@ lwip_netconn_do_close(void *m)
#if LWIP_NETCONN_FULLDUPLEX
if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
/* close requested, abort running write */
sys_sem_t* op_completed_sem;
sys_sem_t* write_completed_sem;
LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
msg->conn->current_msg->err = ERR_CLSD;
msg->conn->current_msg = NULL;
msg->conn->write_offset = 0;
msg->conn->state = NETCONN_NONE;
state = NETCONN_NONE;
NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
sys_sem_signal(op_completed_sem);
sys_sem_signal(write_completed_sem);
} else {
LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
/* In this case, let the write continue and do not interfere with
conn->current_msg or conn->state! */
msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
}
}
if (state == NETCONN_NONE) {
#else /* LWIP_NETCONN_FULLDUPLEX */
msg->err = ERR_INPROGRESS;
#endif /* LWIP_NETCONN_FULLDUPLEX */
} else {
#endif /* LWIP_NETCONN_FULLDUPLEX */
if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
/* Drain and delete mboxes */
netconn_drain(msg->conn);

View File

@@ -64,6 +64,15 @@ static const int err_to_errno_table[] = {
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
EIO /* ERR_ARG -16 Illegal argument. */
};
int
err_to_errno(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
return EIO;
}
return err_to_errno_table[-err];
}
#endif /* !NO_SYS */
#ifdef LWIP_DEBUG
@@ -104,14 +113,3 @@ lwip_strerr(err_t err)
}
#endif /* LWIP_DEBUG */
#if !NO_SYS
int
err_to_errno(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
return EIO;
}
return err_to_errno_table[-err];
}
#endif /* !NO_SYS */

View File

@@ -46,8 +46,8 @@
#include "lwip/api.h"
#include "lwip/dns.h"
#include <string.h>
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdlib.h> /* atoi */
/** helper struct for gethostbyname_r to access the char* buffer */
struct gethostbyname_r_helper {
@@ -382,7 +382,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
#if LWIP_IPV4
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
/* set up sockaddr */
inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr));
sa4->sin_family = AF_INET;
sa4->sin_len = sizeof(struct sockaddr_in);
sa4->sin_port = lwip_htons((u16_t)port_nr);

View File

@@ -82,10 +82,10 @@
(sin)->sin_len = sizeof(struct sockaddr_in); \
(sin)->sin_family = AF_INET; \
(sin)->sin_port = lwip_htons((port)); \
inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \
inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
(port) = lwip_ntohs((sin)->sin_port); }while(0)
#endif /* LWIP_IPV4 */
@@ -407,7 +407,7 @@ alloc_socket(struct netconn *newconn, int accepted)
for (i = 0; i < NUM_SOCKETS; ++i) {
/* Protect socket array */
SYS_ARCH_PROTECT(lev);
if (!sockets[i].conn) {
if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
sockets[i].conn = newconn;
/* The socket is not yet known to anyone, so no need to protect
after having marked it as used. */
@@ -420,7 +420,6 @@ alloc_socket(struct netconn *newconn, int accepted)
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
sockets[i].errevent = 0;
sockets[i].err = 0;
sockets[i].select_waiting = 0;
return i + LWIP_SOCKET_OFFSET;
}
SYS_ARCH_UNPROTECT(lev);
@@ -482,7 +481,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
sock_set_errno(sock, EWOULDBLOCK);
set_errno(EWOULDBLOCK);
return -1;
}
@@ -584,6 +583,14 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
err = netconn_bind(sock->conn, &local_addr, local_port);
if (err != ERR_OK) {
@@ -668,6 +675,14 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) {
unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
err = netconn_connect(sock->conn, &remote_addr, remote_port);
}
@@ -755,7 +770,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
return off;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
sock_set_errno(sock, EWOULDBLOCK);
set_errno(EWOULDBLOCK);
return -1;
}
@@ -847,6 +862,15 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
port = netbuf_fromport((struct netbuf *)buf);
fromaddr = netbuf_fromaddr((struct netbuf *)buf);
}
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
@@ -970,6 +994,10 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
for (i = 0; i < msg->msg_iovlen; i++) {
u8_t apiflags = write_flags;
if (i + 1 < msg->msg_iovlen) {
apiflags |= NETCONN_MORE;
}
written = 0;
err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
if (err == ERR_OK) {
@@ -1066,6 +1094,14 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
if (err == ERR_OK) {
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) {
unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* send the data */
err = netconn_send(sock->conn, chain_buf);
}
@@ -1107,12 +1143,6 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
#endif /* LWIP_TCP */
}
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
/* sockaddr does not match socket type (IPv4/IPv6) */
sock_set_errno(sock, err_to_errno(ERR_VAL));
return -1;
}
/* @todo: split into multiple sendto's? */
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
short_size = (u16_t)size;
@@ -1162,6 +1192,14 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
err = netbuf_ref(&buf, data, short_size);
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
if (err == ERR_OK) {
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) {
unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* send the data */
err = netconn_send(sock->conn, &buf);
}
@@ -1179,9 +1217,7 @@ lwip_socket(int domain, int type, int protocol)
struct netconn *conn;
int i;
#if !LWIP_IPV6
LWIP_UNUSED_ARG(domain); /* @todo: check this */
#endif /* LWIP_IPV6 */
/* create a netconn */
switch (type) {
@@ -1244,7 +1280,7 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
msg.msg_namelen = 0;
/* Hack: we have to cast via number to cast from 'const' pointer to non-const.
Blame the opengroup standard for this inconsistency. */
msg.msg_iov = (struct iovec *)(size_t)iov;
msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov);
msg.msg_iovlen = iovcnt;
msg.msg_control = NULL;
msg.msg_controllen = 0;
@@ -1457,9 +1493,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
SYS_ARCH_PROTECT(lev);
sock = tryget_socket(i);
if (sock != NULL) {
/* @todo: what if this is a new socket (reallocated?) in this case,
select_waiting-- would be wrong (a global 'sockalloc' counter,
stored per socket could help) */
/* for now, handle select_waiting==0... */
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
if (sock->select_waiting > 0) {
sock->select_waiting--;
@@ -1651,8 +1685,7 @@ again:
}
/**
* Unimplemented: Close one end of a full-duplex connection.
* Currently, the full connection is closed.
* Close one end of a full-duplex connection.
*/
int
lwip_shutdown(int s, int how)
@@ -1710,12 +1743,21 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
}
/* get the IP address and port */
/* @todo: this does not work for IPv6, yet */
err = netconn_getaddr(sock->conn, &naddr, &port, local);
if (err != ERR_OK) {
sock_set_errno(sock, err_to_errno(err));
return -1;
}
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
IP_IS_V4_VAL(naddr)) {
ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6);
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
@@ -2001,7 +2043,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
return ENOPROTOOPT;
}
inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
s, *(u32_t *)optval));
break;
@@ -2029,6 +2071,9 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
case IPPROTO_TCP:
/* Special case: all IPPROTO_TCP option take an int */
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
if (sock->conn->pcb.tcp->state == LISTEN) {
return EINVAL;
}
switch (optname) {
case TCP_NODELAY:
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
@@ -2073,10 +2118,6 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
switch (optname) {
case IPV6_V6ONLY:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
/* @todo: this does not work for datagram sockets, yet */
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
return ENOPROTOOPT;
}
*(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
s, *(int *)optval));
@@ -2365,7 +2406,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
{
ip4_addr_t if_addr;
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval);
inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval);
udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
}
break;
@@ -2389,8 +2430,8 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
ip4_addr_t if_addr;
ip4_addr_t multi_addr;
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
if (optname == IP_ADD_MEMBERSHIP) {
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
/* cannot track membership (out of memory) */
@@ -2422,6 +2463,9 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
case IPPROTO_TCP:
/* Special case: all IPPROTO_TCP option take an int */
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
if (sock->conn->pcb.tcp->state == LISTEN) {
return EINVAL;
}
switch (optname) {
case TCP_NODELAY:
if (*(const int*)optval) {
@@ -2469,7 +2513,6 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
/* @todo: this does not work for datagram sockets, yet */
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
if (*(const int*)optval) {
netconn_set_ipv6only(sock->conn, 1);
@@ -2531,6 +2574,12 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
switch (optname) {
#if LWIP_IPV6 && LWIP_RAW
case IPV6_CHECKSUM:
/* It should not be possible to disable the checksum generation with ICMPv6
* as per RFC 3542 chapter 3.1 */
if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
return EINVAL;
}
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW);
if (*(const int *)optval < 0) {
sock->conn->pcb.raw->chksum_reqd = 0;
@@ -2770,7 +2819,7 @@ lwip_socket_drop_registered_memberships(int s)
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE);
netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
}
}
}

View File

@@ -98,11 +98,11 @@
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include <string.h>
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdlib.h> /* atoi */
#include <stdio.h>
#if LWIP_TCP
#if LWIP_TCP && LWIP_CALLBACK_API
/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */
#define MIN_REQ_LEN 7
@@ -335,9 +335,34 @@ char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each ext
/** global list of active HTTP connections, use to kill the oldest when
running out of memory */
static struct http_state *http_connections;
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
static void
http_add_connection(struct http_state *hs)
{
/* add the connection to the list */
hs->next = http_connections;
http_connections = hs;
}
static void
http_remove_connection(struct http_state *hs)
{
/* take the connection off the list */
if (http_connections) {
if (http_connections == hs) {
http_connections = hs->next;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next) {
if (last->next == hs) {
last->next = hs->next;
break;
}
}
}
}
}
static void
http_kill_oldest_connection(u8_t ssi_required)
{
@@ -366,6 +391,11 @@ http_kill_oldest_connection(u8_t ssi_required)
http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */
}
}
#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#define http_add_connection(hs)
#define http_remove_connection(hs)
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#if LWIP_HTTPD_SSI
@@ -422,17 +452,7 @@ http_state_alloc(void)
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
if (ret != NULL) {
http_state_init(ret);
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
/* add the connection to the list */
if (http_connections == NULL) {
http_connections = ret;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next);
LWIP_ASSERT("last != NULL", last != NULL);
last->next = ret;
}
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
http_add_connection(ret);
}
return ret;
}
@@ -481,22 +501,7 @@ http_state_free(struct http_state *hs)
{
if (hs != NULL) {
http_state_eof(hs);
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
/* take the connection off the list */
if (http_connections) {
if (http_connections == hs) {
http_connections = hs->next;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next) {
if (last->next == hs) {
last->next = hs->next;
break;
}
}
}
}
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
http_remove_connection(hs);
HTTP_FREE_HTTP_STATE(hs);
}
}
@@ -638,17 +643,14 @@ http_eof(struct tcp_pcb *pcb, struct http_state *hs)
/* HTTP/1.1 persistent connection? (Not supported for SSI) */
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
if (hs->keepalive) {
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
struct http_state* next = hs->next;
#endif
http_remove_connection(hs);
http_state_eof(hs);
http_state_init(hs);
/* restore state: */
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
hs->next = next;
#endif
hs->pcb = pcb;
hs->keepalive = 1;
http_add_connection(hs);
/* ensure nagle doesn't interfere with sending all data as fast as possible: */
tcp_nagle_disable(pcb);
} else
@@ -1690,7 +1692,14 @@ http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
hs->post_content_len_left -= p->tot_len;
}
}
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
/* prevent connection being closed if httpd_post_data_recved() is called nested */
hs->unrecved_bytes++;
#endif
err = httpd_post_receive_data(hs, p);
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
hs->unrecved_bytes--;
#endif
if (err != ERR_OK) {
/* Ignore remaining content in case of application error */
hs->post_content_len_left = 0;
@@ -1751,8 +1760,8 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
if (content_len >= 0) {
/* adjust length of HTTP header passed to application */
const char *hdr_start_after_uri = uri_end + 1;
u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data);
u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data);
u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
u8_t post_auto_wnd = 1;
http_uri_buf[0] = 0;
/* trim http header */
@@ -2563,6 +2572,7 @@ httpd_init(void)
tcp_setprio(pcb, HTTPD_TCP_PRIO);
/* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
pcb = tcp_listen(pcb);
LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
@@ -2616,4 +2626,4 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
}
#endif /* LWIP_HTTPD_CGI */
#endif /* LWIP_TCP */
#endif /* LWIP_TCP && LWIP_CALLBACK_API */

View File

@@ -53,7 +53,7 @@
#include <string.h>
/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
#if LWIP_IPV4 && LWIP_TCP
#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API
/** Specify the idle timeout (in seconds) after that the test fails */
#ifndef LWIPERF_TCP_MAX_IDLE_SEC
@@ -294,7 +294,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
} else {
/* transmit data */
/* @todo: every x bytes, transmit the settings again */
txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
txlen_max = TCP_MSS;
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
txlen_max = TCP_MSS - 24;
@@ -494,10 +494,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
return ERR_VAL;
}
}
packet_idx += i;
#else
packet_idx += q->len;
#endif
packet_idx += q->len;
}
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
conn->bytes_transferred += packet_idx;
@@ -579,7 +577,7 @@ lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
void*
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
{
return lwiperf_start_tcp_server(IP4_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
report_fn, report_arg);
}
@@ -660,4 +658,4 @@ lwiperf_abort(void* lwiperf_session)
}
}
#endif /* LWIP_IPV4 && LWIP_TCP */
#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */

View File

@@ -52,10 +52,7 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik.ekman@verisure.com>
*
* Please coordinate changes and requests with Erik Ekman
* <erik.ekman@verisure.com>
* Author: Erik Ekman <erik@kryo.se>
*
*/
@@ -68,7 +65,6 @@
#include "lwip/prot/dns.h"
#include <string.h>
#include <stdlib.h>
#if LWIP_MDNS_RESPONDER
@@ -85,13 +81,13 @@
#if LWIP_IPV4
#include "lwip/igmp.h"
/* IPv4 multicast group 224.0.0.251 */
static const ip_addr_t v4group = IPADDR4_INIT(PP_HTONL(0xE00000FBUL));
static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT;
#endif
#if LWIP_IPV6
#include "lwip/mld6.h"
/* IPv6 multicast group FF02::FB */
static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x000000FBUL));
static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT;
#endif
#define MDNS_PORT 5353
@@ -573,7 +569,7 @@ mdns_build_dnssd_domain(struct mdns_domain *domain)
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1));
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP]));
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
return mdns_add_dotlocal(domain);
}
@@ -598,7 +594,7 @@ mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *servi
}
res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service));
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto]));
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
return mdns_add_dotlocal(domain);
}
@@ -1824,6 +1820,7 @@ mdns_resp_init(void)
mdns_pcb->ttl = MDNS_TTL;
#endif
res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT);
LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
udp_recv(mdns_pcb, mdns_recv, NULL);
@@ -2022,7 +2019,7 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service
err_t
mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
{
LWIP_ASSERT("mdns_resp_add_service: service != NULL", service);
LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
/* Use a mdns_domain struct to store txt chunks since it is the same encoding */
return mdns_domain_add_label(&service->txtdata, txt, txt_len);

1341
src/apps/mqtt/mqtt.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -581,7 +581,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
snmp_ip4_to_oid(ip, &test_oid[1]);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i);
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), LWIP_PTR_NUMERIC_CAST(void*, i));
}
}
@@ -589,7 +589,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len);
return ip_NetToMediaTable_get_cell_value_core(LWIP_PTR_NUMERIC_CAST(u8_t, state.reference), column, value, value_len);
}
/* not found */

View File

@@ -36,6 +36,7 @@
#if LWIP_SNMP && SNMP_USE_NETCONN
#include <string.h>
#include "lwip/api.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
@@ -52,7 +53,7 @@ snmp_netconn_thread(void *arg)
LWIP_UNUSED_ARG(arg);
/* Bind to SNMP port with default IP address */
#if LWIP_IPV6
#if LWIP_IPV6
conn = netconn_new(NETCONN_UDP_IPV6);
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT);
#else /* LWIP_IPV6 */

View File

@@ -211,6 +211,7 @@ void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_thread
err_t err = sys_mutex_new(&instance->sem_usage_mutex);
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
err = sys_sem_new(&instance->sem, 0);
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
instance->sync_fn = sync_fn;
}

View File

@@ -573,6 +573,7 @@ sntp_stop(void)
{
if (sntp_pcb != NULL) {
sys_untimeout(sntp_request, NULL);
sys_untimeout(sntp_try_next_server, NULL);
udp_remove(sntp_pcb);
sntp_pcb = NULL;
}
@@ -688,7 +689,7 @@ sntp_getserver(u8_t idx)
if (idx < SNTP_MAX_SERVERS) {
return &sntp_servers[idx].addr;
}
return IP4_ADDR_ANY;
return IP_ADDR_ANY;
}
#if SNTP_SERVER_DNS

View File

@@ -20,6 +20,10 @@
* @ingroup sys_layer
* lwIP provides default implementations for non-standard functions.
* These can be mapped to OS functions to reduce code footprint if desired.
* All defines related to this section must not be placed in lwipopts.h,
* but in arch/cc.h!
* These options cannot be \#defined in lwipopts.h since they are not options
* of lwIP itself, but options of the lwIP port to your system.
*/
/*
@@ -101,13 +105,13 @@ char*
lwip_strnstr(const char* buffer, const char* token, size_t n)
{
const char* p;
int tokenlen = (int)strlen(token);
size_t tokenlen = strlen(token);
if (tokenlen == 0) {
return (char *)(size_t)buffer;
return LWIP_CONST_CAST(char *, buffer);
}
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
return (char *)(size_t)p;
return LWIP_CONST_CAST(char *, p);
}
}
return NULL;

View File

@@ -24,6 +24,11 @@
* the resolver code calls a specified callback function (which
* must be implemented by the module that uses the resolver).
*
* Multicast DNS queries are supported for names ending on ".local".
* However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762
* chapter 5.1), this is not a fully compliant implementation of continuous
* mDNS querying!
*
* All functions must be called from TCPIP thread.
*
* @see @ref netconn_common for thread-safe access.
@@ -71,6 +76,7 @@
/** @todo: define good default values (rfc compliance) */
/** @todo: improve answer parsing, more checkings... */
/** @todo: check RFC1035 - 7.3. Processing responses */
/** @todo: one-shot mDNS: dual-stack fallback to another IP version */
/*-----------------------------------------------------------------------------
* Includes
@@ -116,6 +122,13 @@ static u16_t dns_txid;
#error DNS_MAX_TTL must be a positive 32-bit value
#endif
#if DNS_TABLE_SIZE > 255
#error DNS_TABLE_SIZE must fit into an u8_t
#endif
#if DNS_MAX_SERVERS > 255
#error DNS_MAX_SERVERS must fit into an u8_t
#endif
/* The number of parallel requests (i.e. calls to dns_gethostbyname
* that cannot be answered from the DNS table.
* This is set to the table size by default.
@@ -123,6 +136,10 @@ static u16_t dns_txid;
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
#ifndef DNS_MAX_REQUESTS
#define DNS_MAX_REQUESTS DNS_TABLE_SIZE
#else
#if DNS_MAX_REQUESTS > 255
#error DNS_MAX_REQUESTS must fit into an u8_t
#endif
#endif
#else
/* In this configuration, both arrays have to have the same size and are used
@@ -134,6 +151,10 @@ static u16_t dns_txid;
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
#ifndef DNS_MAX_SOURCE_PORTS
#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
#else
#if DNS_MAX_SOURCE_PORTS > 255
#error DNS_MAX_SOURCE_PORTS must fit into an u8_t
#endif
#endif
#else
#ifdef DNS_MAX_SOURCE_PORTS
@@ -160,6 +181,12 @@ static u16_t dns_txid;
#define LWIP_DNS_SET_ADDRTYPE(x, y)
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
#define LWIP_DNS_ISMDNS_ARG(x) , x
#else
#define LWIP_DNS_ISMDNS_ARG(x)
#endif
/** DNS query message structure.
No packing needed: only used locally on the stack. */
struct dns_query {
@@ -209,6 +236,9 @@ struct dns_table_entry {
#if LWIP_IPV4 && LWIP_IPV6
u8_t reqaddrtype;
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
u8_t is_mdns;
#endif
};
/** DNS request table entry: used when dns_gehostbyname cannot answer the
@@ -250,6 +280,7 @@ DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
static void dns_init_local(void);
static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
#endif /* DNS_LOCAL_HOSTLIST */
@@ -272,6 +303,13 @@ static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
#if LWIP_IPV4
const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT;
#endif /* LWIP_IPV6 */
/**
* Initialize the resolver: set up the UDP pcb and configure the default server
* (if DNS_SERVER_ADDRESS is set).
@@ -329,7 +367,7 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
if (dnsserver != NULL) {
dns_servers[numdns] = (*dnsserver);
} else {
dns_servers[numdns] = *IP4_ADDR_ANY;
dns_servers[numdns] = *IP_ADDR_ANY;
}
}
}
@@ -348,7 +386,7 @@ dns_getserver(u8_t numdns)
if (numdns < DNS_MAX_SERVERS) {
return &dns_servers[numdns];
} else {
return IP4_ADDR_ANY;
return IP_ADDR_ANY;
}
}
@@ -393,6 +431,38 @@ dns_init_local(void)
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
}
/**
* @ingroup dns
* Iterate the local host-list for a hostname.
*
* @param iterator_fn a function that is called for every entry in the local host-list
* @param iterator_arg 3rd argument passed to iterator_fn
* @return the number of entries in the local host-list
*/
size_t
dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg)
{
size_t i;
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
struct local_hostlist_entry *entry = local_hostlist_dynamic;
i = 0;
while (entry != NULL) {
if (iterator_fn != NULL) {
iterator_fn(entry->name, &entry->addr, iterator_arg);
}
i++;
entry = entry->next;
}
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
if (iterator_fn != NULL) {
iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg);
}
}
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
return i;
}
/**
* @ingroup dns
* Scans the local host-list for a hostname.
@@ -400,8 +470,20 @@ dns_init_local(void)
* @param hostname Hostname to look for in the local host-list
* @param addr the first IP address for the hostname in the local host-list or
* IPADDR_NONE if not found.
* @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!)
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!)
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
* @return ERR_OK if found, ERR_ARG if not found
*/
err_t
dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype)
{
LWIP_UNUSED_ARG(dns_addrtype);
return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
}
/* Internal implementation for dns_local_lookup and dns_lookup */
static err_t
dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
{
@@ -665,7 +747,11 @@ dns_send(u8_t idx)
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
(u16_t)(entry->server_idx), entry->name));
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
if (ip_addr_isany_val(dns_servers[entry->server_idx])
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
&& !entry->is_mdns
#endif
) {
/* DNS server not valid anymore, e.g. PPP netif has been shut down */
/* call specified callback function if provided */
dns_call_found(idx, NULL);
@@ -678,6 +764,8 @@ dns_send(u8_t idx)
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
SIZEOF_DNS_QUERY), PBUF_RAM);
if (p != NULL) {
const ip_addr_t* dst;
u16_t dst_port;
/* fill dns header */
memset(&hdr, 0, SIZEOF_DNS_HDR);
hdr.id = lwip_htons(entry->txid);
@@ -720,7 +808,30 @@ dns_send(u8_t idx)
/* send dns packet */
LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
entry->txid, entry->name, entry->server_idx));
err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT);
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
if (entry->is_mdns) {
dst_port = DNS_MQUERY_PORT;
#if LWIP_IPV6
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
{
dst = &dns_mquery_v6group;
}
#endif
#if LWIP_IPV4 && LWIP_IPV6
else
#endif
#if LWIP_IPV4
{
dst = &dns_mquery_v4group;
}
#endif
} else
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
dst_port = DNS_SERVER_PORT;
dst = &dns_servers[entry->server_idx];
}
err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
/* free pbuf */
pbuf_free(p);
@@ -923,7 +1034,11 @@ dns_check_entry(u8_t i)
case DNS_STATE_ASKING:
if (--entry->tmr == 0) {
if (++entry->retries == DNS_MAX_RETRIES) {
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
&& !entry->is_mdns
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
) {
/* change of server */
entry->server_idx++;
entry->tmr = 1;
@@ -1060,10 +1175,15 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
goto memerr; /* ignore this packet */
}
/* Check whether response comes from the same network address to which the
question was sent. (RFC 5452) */
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
goto memerr; /* ignore this packet */
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
if (!entry->is_mdns)
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
/* Check whether response comes from the same network address to which the
question was sent. (RFC 5452) */
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
goto memerr; /* ignore this packet */
}
}
/* Check if the name in the "question" part match with the name in the entry and
@@ -1195,7 +1315,7 @@ memerr:
*/
static err_t
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns))
{
u8_t i;
u8_t lseq, lseqi;
@@ -1244,8 +1364,9 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
}
/* check if this is the oldest completed entry */
if (entry->state == DNS_STATE_DONE) {
if ((u8_t)(dns_seqno - entry->seqno) > lseq) {
lseq = dns_seqno - entry->seqno;
u8_t age = dns_seqno - entry->seqno;
if (age > lseq) {
lseq = age;
lseqi = i;
}
}
@@ -1310,6 +1431,10 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
#endif
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
entry->is_mdns = is_mdns;
#endif
dns_seqno++;
/* force to send query without waiting timer */
@@ -1356,15 +1481,18 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
* ERR_INPROGRESS is returned!)
* @param callback_arg argument to pass to the callback function
* @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
*/
err_t
dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,
void *callback_arg, u8_t dns_addrtype)
{
size_t hostnamelen;
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
u8_t is_mdns;
#endif
/* not initialized or no valid server yet, or invalid addr pointer
* or invalid hostname or invalid hostname length */
if ((addr == NULL) ||
@@ -1421,13 +1549,25 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
LWIP_UNUSED_ARG(dns_addrtype);
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* prevent calling found callback if no server is set, return error instead */
if (ip_addr_isany_val(dns_servers[0])) {
return ERR_VAL;
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) {
is_mdns = 1;
} else {
is_mdns = 0;
}
if (!is_mdns)
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
{
/* prevent calling found callback if no server is set, return error instead */
if (ip_addr_isany_val(dns_servers[0])) {
return ERR_VAL;
}
}
/* queue query with specified callback */
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)
LWIP_DNS_ISMDNS_ARG(is_mdns));
}
#endif /* LWIP_DNS */

View File

@@ -51,7 +51,6 @@
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include <stddef.h>
#include <string.h>
#ifndef LWIP_CHKSUM

View File

@@ -141,7 +141,7 @@ PACK_STRUCT_END
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
#endif
#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
#error "The maximum valid window scale value is 14!"
#endif
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
@@ -218,9 +218,6 @@ PACK_STRUCT_END
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
#endif
#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)"
#endif
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
#endif
@@ -339,6 +336,11 @@ PACK_STRUCT_END
void
lwip_init(void)
{
#ifndef LWIP_SKIP_CONST_CHECK
int a;
LWIP_UNUSED_ARG(a);
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
#endif
#ifndef LWIP_SKIP_PACKING_CHECK
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
#endif

View File

@@ -68,7 +68,6 @@
#include "lwip/etharp.h"
#include "lwip/prot/autoip.h"
#include <stdlib.h>
#include <string.h>
/** Pseudo random macro based on netif informations.
@@ -95,8 +94,6 @@
static err_t autoip_arp_announce(struct netif *netif);
static void autoip_start_probing(struct netif *netif);
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
/**
* @ingroup autoip
* Set a statically allocated struct autoip to work with.
@@ -482,7 +479,8 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
* ip.dst == llipaddr && hw.src != own hwaddr
*/
if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
(ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
(ip4_addr_isany_val(sipaddr) &&
ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Probe Conflict detected\n"));

View File

@@ -103,26 +103,40 @@
#define REBOOT_TRIES 2
#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
#else
#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
#endif
#else
#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
#endif
/** Option handling: options are parsed in dhcp_parse_reply
* and saved in an array where other functions can load them from.
* This might be moved into the struct dhcp (not necessarily since
* lwIP is single-threaded and the array is only used while in recv
* callback). */
#define DHCP_OPTION_IDX_OVERLOAD 0
#define DHCP_OPTION_IDX_MSG_TYPE 1
#define DHCP_OPTION_IDX_SERVER_ID 2
#define DHCP_OPTION_IDX_LEASE_TIME 3
#define DHCP_OPTION_IDX_T1 4
#define DHCP_OPTION_IDX_T2 5
#define DHCP_OPTION_IDX_SUBNET_MASK 6
#define DHCP_OPTION_IDX_ROUTER 7
#define DHCP_OPTION_IDX_DNS_SERVER 8
enum dhcp_option_idx {
DHCP_OPTION_IDX_OVERLOAD = 0,
DHCP_OPTION_IDX_MSG_TYPE,
DHCP_OPTION_IDX_SERVER_ID,
DHCP_OPTION_IDX_LEASE_TIME,
DHCP_OPTION_IDX_T1,
DHCP_OPTION_IDX_T2,
DHCP_OPTION_IDX_SUBNET_MASK,
DHCP_OPTION_IDX_ROUTER,
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
DHCP_OPTION_IDX_DNS_SERVER,
DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
#if LWIP_DHCP_GET_NTP_SRV
#define DHCP_OPTION_IDX_NTP_SERVER (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS)
#else /* LWIP_DHCP_GET_NTP_SRV */
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
DHCP_OPTION_IDX_NTP_SERVER,
DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
#endif /* LWIP_DHCP_GET_NTP_SRV */
DHCP_OPTION_IDX_MAX
};
/** Holds the decoded option values, only valid while in dhcp_recv.
@todo: move this into struct dhcp? */
@@ -135,8 +149,10 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
static u8_t dhcp_discover_request_options[] = {
DHCP_OPTION_SUBNET_MASK,
DHCP_OPTION_ROUTER,
DHCP_OPTION_BROADCAST,
DHCP_OPTION_DNS_SERVER
DHCP_OPTION_BROADCAST
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
, DHCP_OPTION_DNS_SERVER
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
#if LWIP_DHCP_GET_NTP_SRV
, DHCP_OPTION_NTP
#endif /* LWIP_DHCP_GET_NTP_SRV */
@@ -193,8 +209,6 @@ static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif);
/* always add the DHCP options trailer to end and pad */
static void dhcp_option_trailer(struct dhcp *dhcp);
#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
/** Ensure DHCP PCB is allocated and bound */
static err_t
dhcp_inc_pcb_refcount(void)
@@ -572,9 +586,9 @@ dhcp_handle_ack(struct netif *netif)
{
struct dhcp *dhcp = netif_dhcp_data(netif);
#if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV
#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
u8_t n;
#endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
#if LWIP_DHCP_GET_NTP_SRV
ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
#endif
@@ -640,14 +654,14 @@ dhcp_handle_ack(struct netif *netif)
dhcp_set_ntp_servers(n, ntp_server_addrs);
#endif /* LWIP_DHCP_GET_NTP_SRV */
#if LWIP_DNS
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
/* DNS servers */
for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
ip_addr_t dns_addr;
ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
dns_setserver(n, &dns_addr);
}
#endif /* LWIP_DNS */
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
}
/**
@@ -1517,6 +1531,7 @@ again:
LWIP_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;);
@@ -1525,6 +1540,7 @@ again:
LWIP_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;);
decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
@@ -1541,6 +1557,8 @@ again:
#endif /* LWIP_DHCP_GET_NTP_SRV*/
case(DHCP_OPTION_OVERLOAD):
LWIP_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;);
decode_idx = DHCP_OPTION_IDX_OVERLOAD;
break;
case(DHCP_OPTION_MESSAGE_TYPE):

View File

@@ -56,6 +56,10 @@
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */
/** Re-request a used ARP entry 1 minute before it would expire to prevent
@@ -128,7 +132,11 @@ static u8_t etharp_cached_entry;
static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr);
static err_t etharp_raw(struct netif *netif,
const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr,
const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
const u16_t opcode);
#if ARP_QUEUEING
/**
@@ -695,38 +703,12 @@ etharp_input(struct pbuf *p, struct netif *netif)
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
/* ARP request for our address? */
if (for_us) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n"));
/* Re-use pbuf to send ARP reply.
Since we are re-using an existing pbuf, we can't call etharp_raw since
that would allocate a new pbuf. */
hdr->opcode = lwip_htons(ARP_REPLY);
IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif));
LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
(netif->hwaddr_len == ETH_HWADDR_LEN));
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
are already correct, we tested that before */
ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
ETHADDR16_COPY(&hdr->shwaddr, netif->hwaddr);
/* return ARP reply */
#if LWIP_AUTOIP
/* If we are using Link-Local, all ARP packets that contain a Link-Local
* 'sender IP address' MUST be sent using link-layer broadcast instead of
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
ethernet_output(netif, p, &hdr->shwaddr, &ethbroadcast, ETHTYPE_ARP);
} else
#endif /* LWIP_AUTOIP */
{
ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP);
}
/* send ARP response */
etharp_raw(netif,
(struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
(struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
&hdr->shwaddr, &sipaddr,
ARP_REPLY);
/* we are not configured? */
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
@@ -840,7 +822,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
!ip4_addr_islinklocal(ipaddr)) {
#if LWIP_AUTOIP
struct ip_hdr *iphdr = (struct ip_hdr*)(size_t)q->payload;
struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload);
/* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
a link-local source address must always be "directly to its destination
on the same physical link. The host MUST NOT send the packet to any

View File

@@ -51,6 +51,10 @@
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
* used to modify and send a response packet (and to 1 if this is not the case,
* e.g. when link header is stripped of when receiving) */
@@ -81,7 +85,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_DEBUG */
struct icmp_echo_hdr *iecho;
const struct ip_hdr *iphdr_in;
s16_t hlen;
u16_t hlen;
const ip4_addr_t* src;
ICMP_STATS_INC(icmp.recv);
@@ -148,7 +152,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
}
#endif
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
if (pbuf_header(p, (hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
/* p is not big enough to contain link headers
* allocate a new one and copy p into it
*/
@@ -167,7 +171,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
/* copy the ip header */
MEMCPY(r->payload, iphdr_in, hlen);
/* switch r->payload back to icmp header (cannot fail) */
if (pbuf_header(r, -hlen)) {
if (pbuf_header(r, (s16_t)-hlen)) {
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
pbuf_free(r);
goto icmperr;
@@ -194,7 +198,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
/* We generate an answer by switching the dest and src ip addresses,
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
iecho = (struct icmp_echo_hdr *)p->payload;
if (pbuf_header(p, hlen)) {
if (pbuf_header(p, (s16_t)hlen)) {
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
} else {
err_t ret;
@@ -247,7 +251,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (type == ICMP_DUR) {
MIB2_STATS_INC(mib2.icmpindestunreachs);
} else if (type == ICMP_TE) {
MIB2_STATS_INC(mib2.icmpindestunreachs);
MIB2_STATS_INC(mib2.icmpintimeexcds);
} else if (type == ICMP_PP) {
MIB2_STATS_INC(mib2.icmpinparmprobs);
} else if (type == ICMP_SQ) {

View File

@@ -240,10 +240,11 @@ igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
* @return a struct igmp_group*,
* NULL on memory error.
*/
struct igmp_group *
static struct igmp_group *
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
{
struct igmp_group *group;
struct igmp_group *list_head = netif_igmp_data(ifp);
/* Search if the group already exists */
group = igmp_lookfor_group(ifp, addr);
@@ -251,7 +252,7 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
/* Group already exists. */
return group;
}
/* Group doesn't exist yet, create a new one */
group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
if (group != NULL) {
@@ -260,9 +261,21 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
group->group_state = IGMP_GROUP_NON_MEMBER;
group->last_reporter_flag = 0;
group->use = 0;
group->next = netif_igmp_data(ifp);
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
/* Ensure allsystems group is always first in list */
if (list_head == NULL) {
/* this is the first entry in linked list */
LWIP_ASSERT("igmp_lookup_group: first group must be allsystems",
(ip4_addr_cmp(addr, &allsystems) != 0));
group->next = NULL;
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
} else {
/* append _after_ first entry */
LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems",
(ip4_addr_cmp(addr, &allsystems) == 0));
group->next = list_head->next;
list_head->next = group;
}
}
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
@@ -282,24 +295,19 @@ static err_t
igmp_remove_group(struct netif* netif, struct igmp_group *group)
{
err_t err = ERR_OK;
struct igmp_group *tmp_group;
/* Is it the first group? */
if (netif_igmp_data(netif) == group) {
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next);
} else {
/* look for group further down the list */
struct igmp_group *tmpGroup;
for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
if (tmpGroup->next == group) {
tmpGroup->next = group->next;
break;
}
}
/* Group not found in the global igmp_group_list */
if (tmpGroup == NULL) {
err = ERR_ARG;
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) {
if (tmp_group->next == group) {
tmp_group->next = group->next;
break;
}
}
/* Group not found in the global igmp_group_list */
if (tmp_group == NULL) {
err = ERR_ARG;
}
return err;
}

View File

@@ -59,6 +59,10 @@
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** Set this to 0 in the rare case of wanting to call an extra function to
* generate the IP checksum (in contrast to calculating it on-the-fly). */
#ifndef LWIP_INLINE_IP_CHKSUM
@@ -177,7 +181,7 @@ ip4_route(const ip4_addr_t *dest)
/* loopif is disabled, looopback traffic is passed through any netif */
if (ip4_addr_isloopback(dest)) {
/* don't check for link on loopback traffic */
if (netif_is_up(netif_default)) {
if (netif_default != NULL && netif_is_up(netif_default)) {
return netif_default;
}
/* default netif is not up, just use any netif for loopback traffic */
@@ -518,6 +522,15 @@ ip4_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_AUTOIP */
}
if (first) {
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
/* Packets sent to the loopback address must not be accepted on an
* interface that does not have the loopback address assigned to it,
* unless a non-loopback interface is used for loopback traffic. */
if (ip4_addr_isloopback(ip4_current_dest_addr())) {
netif = NULL;
break;
}
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
first = 0;
netif = netif_list;
} else {
@@ -589,6 +602,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
} else
#endif /* IP_FORWARD */
{
IP_STATS_INC(ip.drop);
MIB2_STATS_INC(mib2.ipinaddrerrors);
MIB2_STATS_INC(mib2.ipindiscards);
}
@@ -853,7 +867,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
#if CHECKSUM_GEN_IP_INLINE
chk_sum += LWIP_MAKE_U16(proto, ttl);
chk_sum += PP_NTOHS(proto | (ttl << 8));
#endif /* CHECKSUM_GEN_IP_INLINE */
/* dest cannot be NULL here */
@@ -866,7 +880,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
IPH_TOS_SET(iphdr, tos);
#if CHECKSUM_GEN_IP_INLINE
chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8));
#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
#if CHECKSUM_GEN_IP_INLINE

View File

@@ -183,10 +183,10 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
}
for (;;) {
if (isdigit(c)) {
val = (val * base) + (int)(c - '0');
val = (val * base) + (u32_t)(c - '0');
c = *++cp;
} else if (base == 16 && isxdigit(c)) {
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else {
break;
@@ -310,7 +310,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
do {
rem = *ap % (u8_t)10;
*ap /= (u8_t)10;
inv[i++] = '0' + rem;
inv[i++] = (char)('0' + rem);
} while (*ap);
while (i--) {
if (len++ >= buflen) {

View File

@@ -687,6 +687,8 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
struct pbuf *rambuf;
#if !LWIP_NETIF_TX_SINGLE_PBUF
struct pbuf *newpbuf;
u16_t newpbuflen = 0;
u16_t left_to_copy;
#endif
struct ip_hdr *original_iphdr;
struct ip_hdr *iphdr;
@@ -696,10 +698,6 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
int last;
u16_t poff = IP_HLEN;
u16_t tmp;
#if !LWIP_NETIF_TX_SINGLE_PBUF
u16_t newpbuflen = 0;
u16_t left_to_copy;
#endif
original_iphdr = (struct ip_hdr *)p->payload;
iphdr = original_iphdr;

View File

@@ -62,7 +62,9 @@
* For IPv6 multicast, corresponding Ethernet addresses
* are selected and the packet is transmitted on the link.
*
* For unicast addresses, ...
* For unicast addresses, ask the ND6 module what to do. It will either let us
* send the the packet right away, or queue the packet for later itself, unless
* an error occurs.
*
* @todo anycast addresses
*
@@ -71,14 +73,14 @@
* @param ip6addr The IP address of the packet destination.
*
* @return
* - ERR_RTE No route to destination (no gateway to external networks),
* or the return type of either nd6_queue_packet() or ethernet_output().
* - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue.
*/
err_t
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
{
struct eth_addr dest;
s8_t i;
const u8_t *hwaddr;
err_t result;
/* multicast destination IP address? */
if (ip6_addr_ismulticast(ip6addr)) {
@@ -91,36 +93,26 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
/* Send out. */
return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
}
/* We have a unicast destination IP address */
/* @todo anycast? */
/* Get next hop record. */
i = nd6_get_next_hop_entry(ip6addr, netif);
if (i < 0) {
/* failed to get a next hop neighbor record. */
return ERR_MEM;
/* Ask ND6 what to do with the packet. */
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
if (result != ERR_OK) {
return result;
}
/* Now that we have a destination record, send or queue the packet. */
if (neighbor_cache[i].state == ND6_STALE) {
/* Switch to delay state. */
neighbor_cache[i].state = ND6_DELAY;
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
}
/* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
(neighbor_cache[i].state == ND6_DELAY) ||
(neighbor_cache[i].state == ND6_PROBE)) {
/* Send out. */
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
/* If no hardware address is returned, nd6 has queued the packet for later. */
if (hwaddr == NULL) {
return ERR_OK;
}
/* We should queue packet on this interface. */
return nd6_queue_packet(i, q);
/* Send out the packet using the returned hardware address. */
SMEMCPY(dest.addr, hwaddr, 6);
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
}
#endif /* LWIP_IPV6 && LWIP_ETHERNET */

View File

@@ -60,6 +60,10 @@
#include "lwip/debug.h"
#include "lwip/stats.h"
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/**
* Finds the appropriate network interface for a given IPv6 address. It tries to select
* a netif following a sequence of heuristics:
@@ -94,7 +98,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
if (ip6_addr_islinklocal(dest)) {
if (ip6_addr_isany(src)) {
/* Use default netif, if Up. */
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
if (netif_default == NULL || !netif_is_up(netif_default) ||
!netif_is_link_up(netif_default)) {
return NULL;
}
return netif_default;
@@ -114,7 +119,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
}
/* netif not found, use default netif, if up */
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
if (netif_default == NULL || !netif_is_up(netif_default) ||
!netif_is_link_up(netif_default)) {
return NULL;
}
return netif_default;
@@ -142,15 +148,9 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
}
/* Get the netif for a suitable router. */
i = nd6_select_router(dest, NULL);
if (i >= 0) {
if (default_router_list[i].neighbor_entry != NULL) {
if (default_router_list[i].neighbor_entry->netif != NULL) {
if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
return default_router_list[i].neighbor_entry->netif;
}
}
}
netif = nd6_find_route(dest);
if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) {
return netif;
}
/* try with the netif that matches the source address. */
@@ -172,7 +172,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
/* loopif is disabled, loopback traffic is passed through any netif */
if (ip6_addr_isloopback(dest)) {
/* don't check for link on loopback traffic */
if (netif_is_up(netif_default)) {
if (netif_default != NULL && netif_is_up(netif_default)) {
return netif_default;
}
/* default netif is not up, just use any netif for loopback traffic */
@@ -290,8 +290,9 @@ ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
{
struct netif *netif;
/* do not forward link-local addresses */
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
/* do not forward link-local or loopback addresses */
if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
ip6_addr_isloopback(ip6_current_dest_addr())) {
LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
IP6_STATS_INC(ip6.rterr);
IP6_STATS_INC(ip6.drop);
@@ -446,9 +447,11 @@ ip6_input(struct pbuf *p, struct netif *inp)
ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
/* Don't accept virtual IPv6 mapped IPv4 addresses */
if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src)) ) {
/* Don't accept virtual IPv4 mapped IPv6 addresses.
* Don't accept multicast source addresses. */
if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) ||
ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) {
IP6_STATS_INC(ip6.err);
IP6_STATS_INC(ip6.drop);
return ERR_OK;
@@ -509,12 +512,21 @@ ip6_input(struct pbuf *p, struct netif *inp)
}
}
}
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
/* Do not match link-local addresses to other netifs. */
netif = NULL;
break;
}
if (first) {
if (ip6_addr_islinklocal(ip6_current_dest_addr())
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
|| ip6_addr_isloopback(ip6_current_dest_addr())
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
) {
/* Do not match link-local addresses to other netifs. The loopback
* address is to be considered link-local and packets to it should be
* dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This
* requirement cannot be implemented in the case that loopback
* traffic is sent across a non-loopback interface, however.
*/
netif = NULL;
break;
}
first = 0;
netif = netif_list;
} else {
@@ -709,7 +721,7 @@ netif_found:
options_done:
/* p points to IPv6 header again. */
pbuf_header_force(p, ip_data.current_ip_header_tot_len);
pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len);
/* send to upper layers */
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
@@ -809,8 +821,8 @@ ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
const ip6_addr_t *src_used = src;
if (dest != LWIP_IP_HDRINCL) {
if (src != NULL && ip6_addr_isany(src)) {
src = ip_2_ip6(ip6_select_source_address(netif, dest));
if ((src == NULL) || ip6_addr_isany(src)) {
src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
if ((src_used == NULL) || ip6_addr_isany(src_used)) {
/* No appropriate source address was found for this packet. */
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
IP6_STATS_INC(ip6.rterr);

View File

@@ -132,8 +132,8 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr)
} else if (isxdigit(*s)) {
/* add current digit */
current_block_value = (current_block_value << 4) +
(isdigit(*s) ? *s - '0' :
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
(isdigit(*s) ? (u32_t)(*s - '0') :
(u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
} else {
/* unexpected digit, space? CRLF? */
break;

View File

@@ -379,6 +379,7 @@ ip6_reass(struct pbuf *p)
/* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4).
This cannot fail since we already checked when receiving this fragment. */
u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
}
#else /* IPV6_FRAG_COPYHEADER */
@@ -530,6 +531,7 @@ ip6_reass(struct pbuf *p)
if (IPV6_FRAG_REQROOM > 0) {
/* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */
u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
}
#endif
@@ -546,6 +548,7 @@ ip6_reass(struct pbuf *p)
if (IPV6_FRAG_REQROOM > 0) {
/* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */
u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
}
iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
@@ -610,6 +613,7 @@ nullreturn:
#if LWIP_IPV6 && LWIP_IPV6_FRAG
#if !LWIP_NETIF_TX_SINGLE_PBUF
/** Allocate a new struct pbuf_custom_ref */
static struct pbuf_custom_ref*
ip6_frag_alloc_pbuf_custom_ref(void)
@@ -638,6 +642,7 @@ ip6_frag_free_pbuf_custom(struct pbuf *p)
}
ip6_frag_free_pbuf_custom_ref(pcr);
}
#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
/**
* Fragment an IPv6 datagram if too large for the netif or path MTU.
@@ -658,7 +663,11 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
struct ip6_hdr *ip6hdr;
struct ip6_frag_hdr *frag_hdr;
struct pbuf *rambuf;
#if !LWIP_NETIF_TX_SINGLE_PBUF
struct pbuf *newpbuf;
u16_t newpbuflen = 0;
u16_t left_to_copy;
#endif
static u32_t identification;
u16_t nfb;
u16_t left, cop;
@@ -666,8 +675,6 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
u16_t fragment_offset = 0;
u16_t last;
u16_t poff = IP6_HLEN;
u16_t newpbuflen = 0;
u16_t left_to_copy;
identification++;
@@ -686,6 +693,26 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
/* Fill this fragment */
cop = last ? left : nfb;
#if LWIP_NETIF_TX_SINGLE_PBUF
rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM);
if (rambuf == NULL) {
IP6_FRAG_STATS_INC(ip6_frag.memerr);
return ERR_MEM;
}
LWIP_ASSERT("this needs a pbuf in one piece!",
(rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff);
/* make room for the IP header */
if (pbuf_header(rambuf, IP6_HLEN)) {
pbuf_free(rambuf);
IP6_FRAG_STATS_INC(ip6_frag.memerr);
return ERR_MEM;
}
/* fill in the IP header */
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);
#else
/* When not using a static buffer, create a chain of pbufs.
* The first will be a PBUF_RAM holding the link, IPv6, and Fragment header.
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
@@ -744,6 +771,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
}
}
poff = newpbuflen;
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
/* Set headers */
frag_hdr->_nexth = original_ip6hdr->_nexth;

View File

@@ -573,6 +573,11 @@ mld6_send(struct netif *netif, struct mld_group *group, u8_t type)
/* Add hop-by-hop headers options: router alert with MLD value. */
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
if (type == ICMP6_TYPE_MLR) {
/* Remember we were the last to report */
group->last_reporter_flag = 1;
}
/* Send the packet out. */
MLD6_STATS_INC(mld6.xmit);
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),

View File

@@ -46,6 +46,7 @@
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
#include "lwip/nd6.h"
#include "lwip/priv/nd6_priv.h"
#include "lwip/prot/nd6.h"
#include "lwip/prot/icmp6.h"
#include "lwip/pbuf.h"
@@ -59,9 +60,14 @@
#include "lwip/mld6.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
#include "lwip/dns.h"
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
#endif
@@ -93,10 +99,13 @@ static void nd6_free_neighbor_cache_entry(s8_t i);
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
static s8_t nd6_new_destination_cache_entry(void);
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q);
#define ND6_SEND_FLAG_MULTICAST_DEST 0x01
#define ND6_SEND_FLAG_ALLNODES_DEST 0x02
@@ -155,25 +164,6 @@ nd6_input(struct pbuf *p, struct netif *inp)
* link-layer changed?
* part of DAD mechanism? */
/* Check that link-layer address option also fits in packet. */
if (p->len < (sizeof(struct na_header) + 2)) {
/* @todo debug message */
pbuf_free(p);
ND6_STATS_INC(nd6.lenerr);
ND6_STATS_INC(nd6.drop);
return;
}
lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
/* @todo debug message */
pbuf_free(p);
ND6_STATS_INC(nd6.lenerr);
ND6_STATS_INC(nd6.drop);
return;
}
/* Create an aligned copy. */
ip6_addr_set(&target_address, &(na_hdr->target_address));
@@ -185,12 +175,6 @@ nd6_input(struct pbuf *p, struct netif *inp)
/* We are using a duplicate address. */
netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
#if LWIP_IPV6_MLD
/* Leave solicited node multicast group. */
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]);
mld6_leavegroup_netif(inp, &multicast_address);
#endif /* LWIP_IPV6_MLD */
#if LWIP_IPV6_AUTOCONFIG
/* Check to see if this address was autoconfigured. */
if (!ip6_addr_islinklocal(&target_address)) {
@@ -209,6 +193,25 @@ nd6_input(struct pbuf *p, struct netif *inp)
}
#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
/* Check that link-layer address option also fits in packet. */
if (p->len < (sizeof(struct na_header) + 2)) {
/* @todo debug message */
pbuf_free(p);
ND6_STATS_INC(nd6.lenerr);
ND6_STATS_INC(nd6.drop);
return;
}
lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
/* @todo debug message */
pbuf_free(p);
ND6_STATS_INC(nd6.lenerr);
ND6_STATS_INC(nd6.drop);
return;
}
/* This is an unsolicited NA, most likely there was a LLADDR change. */
i = nd6_find_neighbor_cache_entry(&target_address);
if (i >= 0) {
@@ -390,6 +393,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
struct ra_header *ra_hdr;
u8_t *buffer; /* Used to copy options. */
u16_t offset;
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
/* There can by multiple RDNSS options per RA */
u8_t rdnss_server_idx = 0;
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
/* Check that RA header fits in packet. */
if (p->len < sizeof(struct ra_header)) {
@@ -534,6 +541,37 @@ nd6_input(struct pbuf *p, struct netif *inp)
route_opt = (struct route_option *)buffer;*/
break;
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
case ND6_OPTION_TYPE_RDNSS:
{
u8_t num, n;
struct rdnss_option * rdnss_opt;
rdnss_opt = (struct rdnss_option *)buffer;
num = (rdnss_opt->length - 1) / 2;
for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
ip_addr_t rdnss_address;
/* Get a memory-aligned copy of the prefix. */
ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]);
if (htonl(rdnss_opt->lifetime) > 0) {
/* TODO implement Lifetime > 0 */
dns_setserver(rdnss_server_idx++, &rdnss_address);
} else {
/* TODO implement DNS removal in dns.c */
u8_t s;
for (s = 0; s < DNS_MAX_SERVERS; s++) {
const ip_addr_t *addr = dns_getserver(s);
if(ip_addr_cmp(addr, &rdnss_address)) {
dns_setserver(s, NULL);
}
}
}
}
break;
}
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
default:
/* Unrecognized option, abort. */
ND6_STATS_INC(nd6.proterr);
@@ -549,6 +587,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
{
struct redirect_header *redir_hdr;
struct lladdr_option *lladdr_opt;
ip6_addr_t tmp;
/* Check that Redir header fits in packet. */
if (p->len < sizeof(struct redirect_header)) {
@@ -571,10 +610,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
}
/* Copy original destination address to current source address, to have an aligned copy. */
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address));
ip6_addr_set(&tmp, &(redir_hdr->destination_address));
/* Find dest address in cache */
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
i = nd6_find_destination_cache_entry(&tmp);
if (i < 0) {
/* Destination not in cache, drop packet. */
pbuf_free(p);
@@ -588,15 +627,15 @@ nd6_input(struct pbuf *p, struct netif *inp)
if (lladdr_opt != NULL) {
if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
/* Copy target address to current source address, to have an aligned copy. */
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address));
ip6_addr_set(&tmp, &(redir_hdr->target_address));
i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
i = nd6_find_neighbor_cache_entry(&tmp);
if (i < 0) {
i = nd6_new_neighbor_cache_entry();
if (i >= 0) {
neighbor_cache[i].netif = inp;
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp);
/* Receiving a message does not prove reachability: only in one direction.
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
@@ -622,6 +661,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
struct icmp6_hdr *icmp6hdr; /* Packet too big message */
struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
u32_t pmtu;
ip6_addr_t tmp;
/* Check that ICMPv6 header + IPv6 header fit in payload */
if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) {
@@ -636,10 +676,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr));
/* Copy original destination address to current source address, to have an aligned copy. */
ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest));
ip6_addr_set(&tmp, &(ip6hdr->dest));
/* Look for entry in destination cache. */
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
i = nd6_find_destination_cache_entry(&tmp);
if (i < 0) {
/* Destination not in cache, drop packet. */
pbuf_free(p);
@@ -829,13 +869,6 @@ nd6_tmr(void)
netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
/* @todo implement preferred and valid lifetimes. */
} else if (netif->flags & NETIF_FLAG_UP) {
#if LWIP_IPV6_MLD
if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) == 0) {
/* Join solicited node multicast group. */
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]);
mld6_joingroup_netif(netif, &multicast_address);
}
#endif /* LWIP_IPV6_MLD */
/* Send a NS for this address. */
nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST);
/* tentative: set next state by increasing by one */
@@ -1293,6 +1326,22 @@ nd6_new_destination_cache_entry(void)
return j;
}
/**
* Clear the destination cache.
*
* This operation may be necessary for consistency in the light of changing
* local addresses and/or use of the gateway hook.
*/
void
nd6_clear_destination_cache(void)
{
int i;
for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
ip6_addr_set_any(&destination_cache[i].destination_addr);
}
}
/**
* Determine whether an address matches an on-link prefix.
*
@@ -1328,7 +1377,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
* @return the default router entry index, or -1 if no suitable
* router is found
*/
s8_t
static s8_t
nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
{
s8_t i;
@@ -1380,6 +1429,30 @@ nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
return -1;
}
/**
* Find a router-announced route to the given destination.
*
* The caller is responsible for checking whether the returned netif, if any,
* is in a suitable state (up, link up) to be used for packet transmission.
*
* @param ip6addr the destination IPv6 address
* @return the netif to use for the destination, or NULL if none found
*/
struct netif *
nd6_find_route(const ip6_addr_t *ip6addr)
{
s8_t i;
i = nd6_select_router(ip6addr, NULL);
if (i >= 0) {
if (default_router_list[i].neighbor_entry != NULL) {
return default_router_list[i].neighbor_entry->netif; /* may be NULL */
}
}
return NULL;
}
/**
* Find an entry for a default router.
*
@@ -1416,6 +1489,7 @@ static s8_t
nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
{
s8_t router_index;
s8_t free_router_index;
s8_t neighbor_index;
/* Do we have a neighbor entry for this router? */
@@ -1439,12 +1513,22 @@ nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
neighbor_cache[neighbor_index].isrouter = 1;
/* Look for empty entry. */
for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) {
free_router_index = LWIP_ND6_NUM_ROUTERS;
for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) {
/* check if router already exists (this is a special case for 2 netifs on the same subnet
- e.g. wifi and cable) */
if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){
return router_index;
}
if (default_router_list[router_index].neighbor_entry == NULL) {
default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
return router_index;
/* remember lowest free index to create a new entry */
free_router_index = router_index;
}
}
if (free_router_index < LWIP_ND6_NUM_ROUTERS) {
default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
return free_router_index;
}
/* Could not create a router entry. */
@@ -1521,9 +1605,12 @@ nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif)
* suitable next hop was found, ERR_MEM if no cache entry
* could be created
*/
s8_t
static s8_t
nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
{
#ifdef LWIP_HOOK_ND6_GET_GW
const ip6_addr_t *next_hop_addr;
#endif /* LWIP_HOOK_ND6_GET_GW */
s8_t i;
#if LWIP_NETIF_HWADDRHINT
@@ -1567,6 +1654,12 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
/* Destination in local link. */
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
#ifdef LWIP_HOOK_ND6_GET_GW
} else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) {
/* Next hop for destination provided by hook function. */
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr);
#endif /* LWIP_HOOK_ND6_GET_GW */
} else {
/* We need to select a router. */
i = nd6_select_router(ip6addr, netif);
@@ -1634,7 +1727,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
* @param q packet to be queued
* @return ERR_OK if succeeded, ERR_MEM if out of memory
*/
err_t
static err_t
nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
{
err_t result = ERR_MEM;
@@ -1811,6 +1904,61 @@ nd6_send_q(s8_t i)
#endif /* LWIP_ND6_QUEUEING */
}
/**
* A packet is to be transmitted to a specific IPv6 destination on a specific
* interface. Check if we can find the hardware address of the next hop to use
* for the packet. If so, give the hardware address to the caller, which should
* use it to send the packet right away. Otherwise, enqueue the packet for
* later transmission while looking up the hardware address, if possible.
*
* As such, this function returns one of three different possible results:
*
* - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now.
* - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later.
* - not ERR_OK: something went wrong; forward the error upward in the stack.
*
* @param netif The lwIP network interface on which the IP packet will be sent.
* @param q The pbuf(s) containing the IP packet to be sent.
* @param ip6addr The destination IPv6 address of the packet.
* @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning
* the packet has been queued).
* @return
* - ERR_OK on success, ERR_RTE if no route was found for the packet,
* or ERR_MEM if low memory conditions prohibit sending the packet at all.
*/
err_t
nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp)
{
s8_t i;
/* Get next hop record. */
i = nd6_get_next_hop_entry(ip6addr, netif);
if (i < 0) {
/* failed to get a next hop neighbor record. */
return i;
}
/* Now that we have a destination record, send or queue the packet. */
if (neighbor_cache[i].state == ND6_STALE) {
/* Switch to delay state. */
neighbor_cache[i].state = ND6_DELAY;
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
}
/* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
(neighbor_cache[i].state == ND6_DELAY) ||
(neighbor_cache[i].state == ND6_PROBE)) {
/* Tell the caller to send out the packet now. */
*hwaddrp = neighbor_cache[i].lladdr;
return ERR_OK;
}
/* We should queue packet on this interface. */
*hwaddrp = NULL;
return nd6_queue_packet(i, q);
}
/**
* Get the Path MTU for a destination.
@@ -1917,4 +2065,38 @@ nd6_cleanup_netif(struct netif *netif)
}
}
#if LWIP_IPV6_MLD
/**
* The state of a local IPv6 address entry is about to change. If needed, join
* or leave the solicited-node multicast group for the address.
*
* @param netif The netif that owns the address.
* @param addr_idx The index of the address.
* @param new_state The new (IP6_ADDR_) state for the address.
*/
void
nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state)
{
u8_t old_state, old_member, new_member;
old_state = netif_ip6_addr_state(netif, addr_idx);
/* Determine whether we were, and should be, a member of the solicited-node
* multicast group for this address. For tentative addresses, the group is
* not joined until the address enters the TENTATIVE_1 (or VALID) state. */
old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE);
new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE);
if (old_member != new_member) {
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]);
if (new_member) {
mld6_joingroup_netif(netif, &multicast_address);
} else {
mld6_leavegroup_netif(netif, &multicast_address);
}
}
}
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */

View File

@@ -61,9 +61,13 @@
#include "lwip/err.h"
#include <string.h>
#include <stdlib.h>
#if MEM_LIBC_MALLOC
#include <stdlib.h> /* for malloc()/free() */
#endif
#if MEM_LIBC_MALLOC || MEM_USE_POOLS
/** mem_init is not used when using pools instead of a heap or using
* C library malloc().
*/
@@ -162,7 +166,7 @@ void *
mem_malloc(mem_size_t size)
{
void *ret;
struct memp_malloc_helper *element;
struct memp_malloc_helper *element = NULL;
memp_t poolnr;
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));

View File

@@ -71,11 +71,10 @@
#include "netif/ppp/ppp_opts.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/nd6.h"
#include "lwip/priv/nd6_priv.h"
#include "lwip/ip6_frag.h"
#include "lwip/mld6.h"
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"
@@ -84,6 +83,10 @@ const struct memp_desc* const memp_pools[MEMP_MAX] = {
#include "lwip/priv/memp_std.h"
};
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
#undef MEMP_OVERFLOW_CHECK
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
@@ -209,7 +212,7 @@ memp_overflow_check_all(void)
for (j = 0; j < memp_pools[i]->num; ++j) {
memp_overflow_check_element_overflow(p, memp_pools[i]);
memp_overflow_check_element_underflow(p, memp_pools[i]);
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
}
}
SYS_ARCH_UNPROTECT(old_level);
@@ -301,15 +304,15 @@ do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int
SYS_ARCH_PROTECT(old_level);
memp = *desc->tab;
#if MEMP_OVERFLOW_CHECK == 1
memp_overflow_check_element_overflow(memp, desc);
memp_overflow_check_element_underflow(memp, desc);
#endif /* MEMP_OVERFLOW_CHECK */
#endif /* MEMP_MEM_MALLOC */
if (memp != NULL) {
#if !MEMP_MEM_MALLOC
#if MEMP_OVERFLOW_CHECK == 1
memp_overflow_check_element_overflow(memp, desc);
memp_overflow_check_element_underflow(memp, desc);
#endif /* MEMP_OVERFLOW_CHECK */
*desc->tab = memp->next;
#if MEMP_OVERFLOW_CHECK
memp->next = NULL;

View File

@@ -180,7 +180,7 @@ netif_init(void)
#endif /* NO_SYS */
#if LWIP_IPV6
IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL));
IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
#endif /* LWIP_IPV6 */
@@ -415,7 +415,7 @@ netif_remove(struct netif *netif)
udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
#endif /* LWIP_UDP */
#if LWIP_RAW
raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
#endif /* LWIP_RAW */
}
}
@@ -478,7 +478,7 @@ netif_find(const char *name)
return NULL;
}
num = name[2] - '0';
num = (u8_t)(name[2] - '0');
for (netif = netif_list; netif != NULL; netif = netif->next) {
if (num == netif->num &&
@@ -904,7 +904,6 @@ netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* ad
void
netif_poll(struct netif *netif)
{
struct pbuf *in;
/* If we have a loopif, SNMP counters are adjusted for it,
* if not they are adjusted for 'netif'. */
#if MIB2_STATS
@@ -916,56 +915,52 @@ netif_poll(struct netif *netif)
#endif /* MIB2_STATS */
SYS_ARCH_DECL_PROTECT(lev);
do {
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
SYS_ARCH_PROTECT(lev);
in = netif->loop_first;
if (in != NULL) {
struct pbuf *in_end = in;
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
SYS_ARCH_PROTECT(lev);
while (netif->loop_first != NULL) {
struct pbuf *in, *in_end;
#if LWIP_LOOPBACK_MAX_PBUFS
u8_t clen = 1;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
while (in_end->len != in_end->tot_len) {
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
in_end = in_end->next;
#if LWIP_LOOPBACK_MAX_PBUFS
clen++;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
}
#if LWIP_LOOPBACK_MAX_PBUFS
/* adjust the number of pbufs on queue */
LWIP_ASSERT("netif->loop_cnt_current underflow",
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
netif->loop_cnt_current -= clen;
u8_t clen = 1;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
/* 'in_end' now points to the last pbuf from 'in' */
if (in_end == netif->loop_last) {
/* this was the last pbuf in the list */
netif->loop_first = netif->loop_last = NULL;
} else {
/* pop the pbuf off the list */
netif->loop_first = in_end->next;
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
}
/* De-queue the pbuf from its successors on the 'loop_' list. */
in_end->next = NULL;
in = in_end = netif->loop_first;
while (in_end->len != in_end->tot_len) {
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
in_end = in_end->next;
#if LWIP_LOOPBACK_MAX_PBUFS
clen++;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
}
#if LWIP_LOOPBACK_MAX_PBUFS
/* adjust the number of pbufs on queue */
LWIP_ASSERT("netif->loop_cnt_current underflow",
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
netif->loop_cnt_current -= clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
/* 'in_end' now points to the last pbuf from 'in' */
if (in_end == netif->loop_last) {
/* this was the last pbuf in the list */
netif->loop_first = netif->loop_last = NULL;
} else {
/* pop the pbuf off the list */
netif->loop_first = in_end->next;
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
}
/* De-queue the pbuf from its successors on the 'loop_' list. */
in_end->next = NULL;
SYS_ARCH_UNPROTECT(lev);
if (in != NULL) {
LINK_STATS_INC(link.recv);
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
/* loopback packets are always IP packets! */
if (ip_input(in, netif) != ERR_OK) {
pbuf_free(in);
}
/* Don't reference the packet any more! */
in = NULL;
LINK_STATS_INC(link.recv);
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
/* loopback packets are always IP packets! */
if (ip_input(in, netif) != ERR_OK) {
pbuf_free(in);
}
/* go on while there is a packet on the list */
} while (netif->loop_first != NULL);
SYS_ARCH_PROTECT(lev);
}
SYS_ARCH_UNPROTECT(lev);
}
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
@@ -1058,7 +1053,7 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1,
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
#endif /* LWIP_UDP */
#if LWIP_RAW
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
#endif /* LWIP_RAW */
}
/* @todo: remove/readd mib2 ip6 entries? */
@@ -1101,6 +1096,13 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
u8_t new_valid = state & IP6_ADDR_VALID;
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
#if LWIP_IPV6_MLD
/* Reevaluate solicited-node multicast group membership. */
if (netif->flags & NETIF_FLAG_MLD6) {
nd6_adjust_mld_membership(netif, addr_idx, state);
}
#endif /* LWIP_IPV6_MLD */
if (old_valid && !new_valid) {
/* address about to be removed by setting invalid */
#if LWIP_TCP
@@ -1110,7 +1112,7 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
#endif /* LWIP_UDP */
#if LWIP_RAW
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
#endif /* LWIP_RAW */
/* @todo: remove mib2 ip6 entries? */
}
@@ -1200,10 +1202,10 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
/* Set address state. */
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
/* Will perform duplicate address detection (DAD). */
netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
#else
/* Consider address valid. */
netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
#endif /* LWIP_IPV6_AUTOCONFIG */
}
@@ -1233,7 +1235,7 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos
/* Find a free slot -- musn't be the first one (reserved for link local) */
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
if (chosen_idx != NULL) {

View File

@@ -350,8 +350,18 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
break;
case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
{
mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length);
/* bug #50040: Check for integer overflow when calculating alloc_len */
if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) {
return NULL;
}
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = (struct pbuf*)mem_malloc(alloc_len);
}
if (p == NULL) {
return NULL;
}
@@ -568,11 +578,11 @@ pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
}
if (header_size_increment < 0) {
increment_magnitude = -header_size_increment;
increment_magnitude = (u16_t)-header_size_increment;
/* Check that we aren't going to move off the end of the pbuf */
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
} else {
increment_magnitude = header_size_increment;
increment_magnitude = (u16_t)header_size_increment;
#if 0
/* Can't assert these as some callers speculatively call
pbuf_header() to see if it's OK. Will return 1 below instead. */
@@ -812,6 +822,7 @@ pbuf_ref(struct pbuf *p)
/* pbuf given? */
if (p != NULL) {
SYS_ARCH_INC(p->ref, 1);
LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
}
}
@@ -1119,7 +1130,8 @@ pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset)
struct pbuf*
pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
{
return (struct pbuf*)(size_t)pbuf_skip_const(in, in_offset, out_offset);
const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset);
return LWIP_CONST_CAST(struct pbuf*, out);
}
/**
@@ -1227,6 +1239,7 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
return p;
}
err = pbuf_copy(q, p);
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
pbuf_free(p);
return q;

View File

@@ -209,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
err_t
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
@@ -233,7 +233,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
err_t
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
@@ -320,7 +320,13 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
}
}
netif = ip_route(&pcb->local_ip, ipaddr);
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
/* Don't call ip_route() with IP_ANY_TYPE */
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
} else {
netif = ip_route(&pcb->local_ip, ipaddr);
}
if (netif == NULL) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);

View File

@@ -96,7 +96,7 @@ stats_display_igmp(struct stats_igmp *igmp, const char *name)
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report));
}
#endif /* IGMP_STATS || MLD6_STATS */
@@ -135,7 +135,7 @@ stats_display_sys(struct stats_sys *sys)
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err));
}
#endif /* SYS_STATS */

View File

@@ -36,6 +36,44 @@
*
*/
/**
* @defgroup sys_layer Porting (system abstraction layer)
* @ingroup lwip
* @verbinclude "sys_arch.txt"
*
* @defgroup sys_os OS abstraction layer
* @ingroup sys_layer
* No need to implement functions in this section in NO_SYS mode.
*
* @defgroup sys_sem Semaphores
* @ingroup sys_os
*
* @defgroup sys_mutex Mutexes
* @ingroup sys_os
* Mutexes are recommended to correctly handle priority inversion,
* especially if you use LWIP_CORE_LOCKING .
*
* @defgroup sys_mbox Mailboxes
* @ingroup sys_os
*
* @defgroup sys_time Time
* @ingroup sys_layer
*
* @defgroup sys_prot Critical sections
* @ingroup sys_layer
* Used to protect short regions of code against concurrent access.
* - Your system is a bare-metal system (probably with an RTOS)
* and interrupts are under your control:
* Implement this as LockInterrupts() / UnlockInterrupts()
* - Your system uses an RTOS with deferred interrupt handling from a
* worker thread: Implement as a global mutex or lock/unlock scheduler
* - Your system uses a high-level OS with e.g. POSIX signals:
* Implement as a global mutex
*
* @defgroup sys_misc Misc
* @ingroup sys_os
*/
#include "lwip/opt.h"
#include "lwip/sys.h"

View File

@@ -62,6 +62,10 @@
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#ifndef TCP_LOCAL_PORT_RANGE_START
/* From http://www.iana.org/assignments/port-numbers:
"The Dynamic and/or Private Ports are those from 49152 through 65535" */
@@ -132,6 +136,8 @@ static u8_t tcp_timer;
static u8_t tcp_timer_ctr;
static u16_t tcp_new_port(void);
static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
/**
* Initialize this module.
*/
@@ -258,8 +264,6 @@ tcp_backlog_accepted(struct tcp_pcb* pcb)
static err_t
tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
{
err_t err;
if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) {
/* Not all data received by application, send RST to tell the remote
@@ -290,6 +294,8 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
}
}
/* - states which free the pcb are handled here,
- states which send FIN and change state are handled in tcp_close_shutdown_fin() */
switch (pcb->state) {
case CLOSED:
/* Closing a pcb in the CLOSED state might seem erroneous,
@@ -299,27 +305,34 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
* or for a pcb that has been used and then entered the CLOSED state
* is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */
err = ERR_OK;
if (pcb->local_port != 0) {
TCP_RMV(&tcp_bound_pcbs, pcb);
}
memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
break;
case LISTEN:
err = ERR_OK;
tcp_listen_closed(pcb);
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
break;
case SYN_SENT:
err = ERR_OK;
TCP_PCB_REMOVE_ACTIVE(pcb);
memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
MIB2_STATS_INC(mib2.tcpattemptfails);
break;
default:
return tcp_close_shutdown_fin(pcb);
}
return ERR_OK;
}
static err_t
tcp_close_shutdown_fin(struct tcp_pcb *pcb)
{
err_t err;
LWIP_ASSERT("pcb != NULL", pcb != NULL);
switch (pcb->state) {
case SYN_RCVD:
err = tcp_send_fin(pcb);
if (err == ERR_OK) {
@@ -344,18 +357,20 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
break;
default:
/* Has already been closed, do nothing. */
err = ERR_OK;
pcb = NULL;
return ERR_OK;
break;
}
if (pcb != NULL && err == ERR_OK) {
if (err == ERR_OK) {
/* To ensure all data has been sent when tcp_close returns, we have
to make sure tcp_output doesn't fail.
Since we don't really have to ensure all data has been sent when tcp_close
returns (unsent data is sent from tcp timer functions, also), we don't care
for the return value of tcp_output for now. */
tcp_output(pcb);
} else if (err == ERR_MEM) {
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
pcb->flags |= TF_CLOSEPEND;
}
return err;
}
@@ -467,6 +482,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} else {
int send_rst = 0;
u16_t local_port = 0;
enum tcp_state last_state;
seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt;
#if LWIP_CALLBACK_API
@@ -499,8 +515,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
}
last_state = pcb->state;
memp_free(MEMP_TCP_PCB, pcb);
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT);
}
}
@@ -551,7 +568,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -636,19 +653,44 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
*
* @note The original tcp_pcb is freed. This function therefore has to be
* called like this:
* tpcb = tcp_listen(tpcb);
* tpcb = tcp_listen_with_backlog(tpcb, backlog);
*/
struct tcp_pcb *
tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
{
struct tcp_pcb_listen *lpcb;
return tcp_listen_with_backlog_and_err(pcb, backlog, NULL);
}
/**
* @ingroup tcp_raw
* Set the state of the connection to be LISTEN, which means that it
* is able to accept incoming connections. The protocol control block
* is reallocated in order to consume less memory. Setting the
* connection to LISTEN is an irreversible process.
*
* @param pcb the original tcp_pcb
* @param backlog the incoming connections queue limit
* @param err when NULL is returned, this contains the error reason
* @return tcp_pcb used for listening, consumes less memory.
*
* @note The original tcp_pcb is freed. This function therefore has to be
* called like this:
* tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err);
*/
struct tcp_pcb *
tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
{
struct tcp_pcb_listen *lpcb = NULL;
err_t res;
LWIP_UNUSED_ARG(backlog);
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done);
/* already listening? */
if (pcb->state == LISTEN) {
return pcb;
lpcb = (struct tcp_pcb_listen*)pcb;
res = ERR_ALREADY;
goto done;
}
#if SO_REUSE
if (ip_get_option(pcb, SOF_REUSEADDR)) {
@@ -659,14 +701,17 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
if ((lpcb->local_port == pcb->local_port) &&
ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
/* this address/port is already used */
return NULL;
lpcb = NULL;
res = ERR_USE;
goto done;
}
}
}
#endif /* SO_REUSE */
lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
if (lpcb == NULL) {
return NULL;
res = ERR_MEM;
goto done;
}
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
@@ -691,6 +736,11 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
tcp_backlog_set(lpcb, backlog);
#endif /* TCP_LISTEN_BACKLOG */
TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
res = ERR_OK;
done:
if (err != NULL) {
*err = res;
}
return (struct tcp_pcb *)lpcb;
}
@@ -826,7 +876,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
u32_t iss;
u16_t old_local_port;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -880,10 +930,11 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
#endif /* SO_REUSE */
}
iss = tcp_next_iss();
iss = tcp_next_iss(pcb);
pcb->rcv_nxt = 0;
pcb->snd_nxt = iss;
pcb->lastack = iss - 1;
pcb->snd_wl2 = iss - 1;
pcb->snd_lbb = iss - 1;
/* Start with a window that does not need scaling. When window scaling is
enabled and used, the window is enlarged when both sides agree on scaling. */
@@ -897,7 +948,6 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1;
pcb->ssthresh = TCP_WND;
#if LWIP_CALLBACK_API
pcb->connected = connected;
#else /* LWIP_CALLBACK_API */
@@ -963,11 +1013,11 @@ tcp_slowtmr_start:
pcb_remove = 0;
pcb_reset = 0;
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
}
else if (pcb->nrtx == TCP_MAXRTX) {
else if (pcb->nrtx >= TCP_MAXRTX) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
} else {
@@ -1001,7 +1051,8 @@ tcp_slowtmr_start:
/* Double retransmission time-out unless we are trying to
* connect to somebody (i.e., we are in SYN_SENT). */
if (pcb->state != SYN_SENT) {
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1);
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx];
}
/* Reset the retransmission timer. */
@@ -1098,6 +1149,7 @@ tcp_slowtmr_start:
tcp_err_fn err_fn = pcb->errf;
#endif /* LWIP_CALLBACK_API */
void *err_arg;
enum tcp_state last_state;
tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) {
@@ -1115,12 +1167,13 @@ tcp_slowtmr_start:
}
err_arg = pcb->callback_arg;
last_state = pcb->state;
pcb2 = pcb;
pcb = pcb->next;
memp_free(MEMP_TCP_PCB, pcb2);
tcp_active_pcbs_changed = 0;
TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT);
TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT);
if (tcp_active_pcbs_changed) {
goto tcp_slowtmr_start;
}
@@ -1210,6 +1263,12 @@ tcp_fasttmr_start:
tcp_output(pcb);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
/* send pending FIN */
if (pcb->flags & TF_CLOSEPEND) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n"));
pcb->flags &= ~(TF_CLOSEPEND);
tcp_close_shutdown_fin(pcb);
}
next = pcb->next;
@@ -1491,7 +1550,6 @@ struct tcp_pcb *
tcp_alloc(u8_t prio)
{
struct tcp_pcb *pcb;
u32_t iss;
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) {
@@ -1554,14 +1612,17 @@ tcp_alloc(u8_t prio)
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
pcb->rtime = -1;
pcb->cwnd = 1;
iss = tcp_next_iss();
pcb->snd_wl2 = iss;
pcb->snd_nxt = iss;
pcb->lastack = iss;
pcb->snd_lbb = iss;
pcb->tmr = tcp_ticks;
pcb->last_timer = tcp_timer_ctr;
/* RFC 5681 recommends setting ssthresh abritrarily high and gives an example
of using the largest advertised receive window. We've seen complications with
receiving TCPs that use window scaling and/or window auto-tuning where the
initial advertised window is very small and then grows rapidly once the
connection is established. To avoid these complications, we set ssthresh to the
largest effective cwnd (amount of in-flight data) that the sender can have. */
pcb->ssthresh = TCP_SND_BUF;
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
@@ -1826,12 +1887,18 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
* @return u32_t pseudo random sequence number
*/
u32_t
tcp_next_iss(void)
tcp_next_iss(struct tcp_pcb *pcb)
{
#ifdef LWIP_HOOK_TCP_ISN
return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port);
#else /* LWIP_HOOK_TCP_ISN */
static u32_t iss = 6510;
LWIP_UNUSED_ARG(pcb);
iss += tcp_ticks; /* XXX */
return iss;
#endif /* LWIP_HOOK_TCP_ISN */
}
#if TCP_CALCULATE_EFF_SEND_MSS

View File

@@ -61,8 +61,6 @@
/** Initial CWND calculation as defined RFC 2581 */
#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
/** Initial slow start threshold value: we use the full window */
#define LWIP_TCP_INITIAL_SSTHRESH(pcb) ((pcb)->snd_wnd)
/* These variables are global to all functions involved in the input
processing of TCP segments. They are set by the tcp_input()
@@ -358,6 +356,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
((pcb->refused_data != NULL) && (tcplen > 0))) {
/* pcb has been aborted or refused data is still refused and the new
segment contains data */
if (pcb->rcv_ann_wnd == 0) {
/* this is a zero-window probe, we respond to it with current RCV.NXT
and drop the data segment */
tcp_send_empty_ack(pcb);
}
TCP_STATS_INC(tcp.drop);
MIB2_STATS_INC(mib2.tcpinerrs);
goto aborted;
@@ -373,7 +376,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
end. We then call the error callback to inform the
application that the connection is dead before we
deallocate the PCB. */
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
} else {
@@ -408,7 +411,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
}
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
@@ -542,6 +545,7 @@ static void
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
struct tcp_pcb *npcb;
u32_t iss;
err_t rc;
if (flags & TCP_RST) {
@@ -589,6 +593,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->state = SYN_RCVD;
npcb->rcv_nxt = seqno + 1;
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
iss = tcp_next_iss(npcb);
npcb->snd_wl2 = iss;
npcb->snd_nxt = iss;
npcb->lastack = iss;
npcb->snd_lbb = iss;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
@@ -602,9 +611,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
/* Parse any options in the SYN. */
tcp_parseopt(npcb);
npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd);
npcb->snd_wnd = tcphdr->wnd;
npcb->snd_wnd_max = npcb->snd_wnd;
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
@@ -751,7 +759,7 @@ tcp_process(struct tcp_pcb *pcb)
pcb->rcv_nxt = seqno + 1;
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
pcb->lastack = ackno;
pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
pcb->snd_wnd = tcphdr->wnd;
pcb->snd_wnd_max = pcb->snd_wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED;
@@ -760,9 +768,6 @@ tcp_process(struct tcp_pcb *pcb)
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
/* Set ssthresh again after changing 'mss' and 'snd_wnd' */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
" ssthresh %"TCPWNDSIZE_F"\n",
@@ -805,9 +810,12 @@ tcp_process(struct tcp_pcb *pcb)
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
/* Resend SYN immediately (don't wait for rto timeout) to establish
connection faster */
pcb->rtime = 0;
tcp_rexmit_rto(pcb);
connection faster, but do not send more SYNs than we otherwise would
have, or we might get caught in a loop on loopback interfaces. */
if (pcb->nrtx < TCP_SYNMAXRTX) {
pcb->rtime = 0;
tcp_rexmit_rto(pcb);
}
}
break;
case SYN_RCVD:
@@ -816,14 +824,16 @@ tcp_process(struct tcp_pcb *pcb)
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
#if LWIP_CALLBACK_API
LWIP_ASSERT("pcb->listener->accept != NULL",
(pcb->listener == NULL) || (pcb->listener->accept != NULL));
#endif
if (pcb->listener == NULL) {
/* listen pcb might be closed by now */
err = ERR_VAL;
} else
#endif
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
{
tcp_backlog_accepted(pcb);
/* Call the accept function. */
@@ -842,11 +852,6 @@ tcp_process(struct tcp_pcb *pcb)
* we'd better pass it on to the application as well. */
tcp_receive(pcb);
/* passive open: update initial ssthresh now that the correct window is
known: if the remote side supports window scaling, the window sent
with the initial SYN can be smaller than the one used later */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
/* Prevent ACK for SYN to generate a sent event */
if (recv_acked != 0) {
recv_acked--;
@@ -914,7 +919,7 @@ tcp_process(struct tcp_pcb *pcb)
break;
case CLOSING:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_pcb_purge(pcb);
TCP_RMV_ACTIVE(pcb);
@@ -924,7 +929,7 @@ tcp_process(struct tcp_pcb *pcb)
break;
case LAST_ACK:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
recv_flags |= TF_CLOSED;
@@ -1406,7 +1411,7 @@ tcp_receive(struct tcp_pcb *pcb)
TCP_SEQ_GEQ(seqno + tcplen,
next->tcphdr->seqno + next->len)) {
/* inseg cannot have FIN here (already processed above) */
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
tcplen = TCP_TCPLEN(&inseg);

View File

@@ -376,7 +376,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#if TCP_OVERSIZE
u16_t oversize = 0;
u16_t oversize_used = 0;
#if TCP_OVERSIZE_DBGCHECK
u16_t oversize_add = 0;
#endif /* TCP_OVERSIZE_DBGCHECK*/
#endif /* TCP_OVERSIZE */
u16_t extendlen = 0;
#if TCP_CHECKSUM_ON_COPY
u16_t concat_chksum = 0;
u8_t concat_chksum_swapped = 0;
@@ -460,13 +464,13 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
*/
#if TCP_OVERSIZE
#if TCP_OVERSIZE_DBGCHECK
/* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
/* check that pcb->unsent_oversize matches last_unsent->oversize_left */
LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
pcb->unsent_oversize == last_unsent->oversize_left);
#endif /* TCP_OVERSIZE_DBGCHECK */
oversize = pcb->unsent_oversize;
if (oversize > 0) {
LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space);
seg = last_unsent;
oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
pos += oversize_used;
@@ -474,18 +478,22 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
space -= oversize_used;
}
/* now we are either finished or oversize is zero */
LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len));
#endif /* TCP_OVERSIZE */
/*
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
*
* As an exception when NOT copying the data, if the given data buffer
* directly follows the last unsent data buffer in memory, extend the last
* ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation.
*
* We don't extend segments containing SYN/FIN flags or options
* (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
* the end.
*/
if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
u16_t seglen = space < len - pos ? space : len - pos;
u16_t seglen = LWIP_MIN(space, len - pos);
seg = last_unsent;
/* Create a pbuf with a copy or reference to seglen bytes. We
@@ -500,18 +508,30 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
goto memerr;
}
#if TCP_OVERSIZE_DBGCHECK
last_unsent->oversize_left += oversize;
oversize_add = oversize;
#endif /* TCP_OVERSIZE_DBGCHECK */
TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
#if TCP_CHECKSUM_ON_COPY
concat_chksummed += seglen;
#endif /* TCP_CHECKSUM_ON_COPY */
queuelen += pbuf_clen(concat_p);
} else {
/* Data is not copied */
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
goto memerr;
/* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */
struct pbuf *p;
for (p = last_unsent->p; p->next != NULL; p = p->next);
if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) {
LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0);
extendlen = seglen;
} else {
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
goto memerr;
}
/* reference the non-volatile payload data */
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
queuelen += pbuf_clen(concat_p);
}
#if TCP_CHECKSUM_ON_COPY
/* calculate the checksum of nocopy-data */
@@ -519,12 +539,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
&concat_chksum, &concat_chksum_swapped);
concat_chksummed += seglen;
#endif /* TCP_CHECKSUM_ON_COPY */
/* reference the non-volatile payload data */
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
}
pos += seglen;
queuelen += pbuf_clen(concat_p);
}
} else {
#if TCP_OVERSIZE
@@ -543,7 +560,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
struct pbuf *p;
u16_t left = len - pos;
u16_t max_len = mss_local - optlen;
u16_t seglen = left > max_len ? max_len : left;
u16_t seglen = LWIP_MIN(left, max_len);
#if TCP_CHECKSUM_ON_COPY
u16_t chksum = 0;
u8_t chksum_swapped = 0;
@@ -642,6 +659,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
* All three segmentation phases were successful. We can commit the
* transaction.
*/
#if TCP_OVERSIZE_DBGCHECK
if ((last_unsent != NULL) && (oversize_add != 0)) {
last_unsent->oversize_left += oversize_add;
}
#endif /* TCP_OVERSIZE_DBGCHECK */
/*
* Phase 1: If data has been added to the preallocated tail of
@@ -669,26 +691,40 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#endif /* TCP_OVERSIZE */
/*
* Phase 2: concat_p can be concatenated onto last_unsent->p
* Phase 2: concat_p can be concatenated onto last_unsent->p, unless we
* determined that the last ROM pbuf can be extended to include the new data.
*/
if (concat_p != NULL) {
LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
(last_unsent != NULL));
pbuf_cat(last_unsent->p, concat_p);
last_unsent->len += concat_p->tot_len;
#if TCP_CHECKSUM_ON_COPY
if (concat_chksummed) {
/*if concat checksumm swapped - swap it back */
if (concat_chksum_swapped) {
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
}
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
&last_unsent->chksum_swapped);
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
} else if (extendlen > 0) {
struct pbuf *p;
LWIP_ASSERT("tcp_write: extension of reference requires reference",
last_unsent != NULL && last_unsent->p != NULL);
for (p = last_unsent->p; p->next != NULL; p = p->next) {
p->tot_len += extendlen;
}
#endif /* TCP_CHECKSUM_ON_COPY */
p->tot_len += extendlen;
p->len += extendlen;
last_unsent->len += extendlen;
}
#if TCP_CHECKSUM_ON_COPY
if (concat_chksummed) {
LWIP_ASSERT("tcp_write: concat checksum needs concatenated data",
concat_p != NULL || extendlen > 0);
/*if concat checksumm swapped - swap it back */
if (concat_chksum_swapped) {
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
}
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
&last_unsent->chksum_swapped);
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
}
#endif /* TCP_CHECKSUM_ON_COPY */
/*
* Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
* is harmless
@@ -1033,6 +1069,24 @@ tcp_output(struct tcp_pcb *pcb)
lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
}
#endif /* TCP_CWND_DEBUG */
/* Check if we need to start the persistent timer when the next unsent segment
* does not fit within the remaining send window and RTO timer is not running (we
* have no in-flight data). A traditional approach would fill the remaining window
* with part of the unsent segment (which will engage zero-window probing upon
* reception of the zero window update from the receiver). This ensures the
* subsequent window update is reliably received. With the goal of being lightweight,
* we avoid splitting the unsent segment and treat the window as already zero.
*/
if (seg != NULL &&
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
/* Start the persist timer */
if (pcb->persist_backoff == 0) {
pcb->persist_cnt = 0;
pcb->persist_backoff = 1;
}
goto output_done;
}
/* data available and window allows it to be sent? */
while (seg != NULL &&
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
@@ -1112,6 +1166,7 @@ tcp_output(struct tcp_pcb *pcb)
}
seg = pcb->unsent;
}
output_done:
#if TCP_OVERSIZE
if (pcb->unsent == NULL) {
/* last unsent has been removed, reset unsent_oversize */
@@ -1365,7 +1420,9 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
pcb->unacked = NULL;
/* increment number of retransmissions */
++pcb->nrtx;
if (pcb->nrtx < 0xFF) {
++pcb->nrtx;
}
/* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0;
@@ -1410,7 +1467,9 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
#endif /* TCP_OVERSIZE */
++pcb->nrtx;
if (pcb->nrtx < 0xFF) {
++pcb->nrtx;
}
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;
@@ -1441,11 +1500,7 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
/* Set ssthresh to half of the minimum of the current
* cwnd and the advertised window */
if (pcb->cwnd > pcb->snd_wnd) {
pcb->ssthresh = pcb->snd_wnd / 2;
} else {
pcb->ssthresh = pcb->cwnd / 2;
}
pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
/* The minimum value for ssthresh should be 2 MSS */
if (pcb->ssthresh < (2U * pcb->mss)) {

View File

@@ -179,7 +179,7 @@ void sys_timeouts_init(void)
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
/* we have to cast via size_t to get rid of const warning
(this is OK as cyclic_timer() casts back to const* */
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, (void*)(size_t)&lwip_cyclic_timers[i]);
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
}
/* Initialise timestamp for sys_check_timeouts */

View File

@@ -116,24 +116,6 @@ again:
}
}
return udp_port;
#if 0
struct udp_pcb *ipcb = udp_pcbs;
while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
if (ipcb->local_port == udp_port) {
/* port is already used by another udp_pcb */
udp_port++;
/* restart scanning all udp pcbs */
ipcb = udp_pcbs;
} else {
/* go on with next udp pcb */
ipcb = ipcb->next;
}
}
if (ipcb != NULL) {
return 0;
}
return udp_port;
#endif
}
/** Common code to see if the current input packet matches the pcb
@@ -178,15 +160,8 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast)
}
} else
#endif /* LWIP_IPV4 */
/* Handle IPv4 and IPv6: all, multicast or exact match */
if (ip_addr_isany(&pcb->local_ip) ||
#if LWIP_IPV6_MLD
(ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) ||
#endif /* LWIP_IPV6_MLD */
#if LWIP_IGMP
(!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) ||
#endif /* LWIP_IGMP */
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
/* Handle IPv4 and IPv6: all or exact match */
if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
return 1;
}
}
@@ -429,7 +404,7 @@ udp_input(struct pbuf *p, struct netif *inp)
destination address was broadcast/multicast. */
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
/* move payload pointer back to ip header */
pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN);
pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN));
icmp_port_unreach(ip_current_is_v6(), p);
}
#endif /* LWIP_ICMP || LWIP_ICMP6 */
@@ -571,7 +546,12 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */
/* find the outgoing network interface for this packet */
netif = ip_route(&pcb->local_ip, dst_ip_route);
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
/* Don't call ip_route() with IP_ANY_TYPE */
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route);
} else {
netif = ip_route(&pcb->local_ip, dst_ip_route);
}
/* no outgoing network interface could be found? */
if (netif == NULL) {
@@ -662,7 +642,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_i
* this could be an old address if netif->ip_addr has changed */
if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {
/* local_ip doesn't match, drop the packet */
return ERR_VAL;
return ERR_RTE;
}
/* use UDP PCB local IP address as source address */
src_ip = &pcb->local_ip;
@@ -912,7 +892,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -1002,7 +982,7 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}

View File

@@ -43,8 +43,7 @@
/* Note: Netconn API is always available when sockets are enabled -
* sockets are implemented on top of them */
#include <stddef.h> /* for size_t */
#include "lwip/arch.h"
#include "lwip/netbuf.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
@@ -90,6 +89,7 @@ extern "C" {
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
#else /* LWIP_IPV6 */
#define NETCONNTYPE_ISIPV6(t) (0)
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
#endif /* LWIP_IPV6 */

View File

@@ -31,7 +31,7 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik.ekman@verisure.com>
* Author: Erik Ekman <erik@kryo.se>
*
*/
#ifndef LWIP_HDR_MDNS_H

View File

@@ -31,7 +31,7 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik.ekman@verisure.com>
* Author: Erik Ekman <erik@kryo.se>
*
*/

View File

@@ -31,7 +31,7 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik.ekman@verisure.com>
* Author: Erik Ekman <erik@kryo.se>
*
*/
#ifndef LWIP_HDR_MDNS_PRIV_H

View File

@@ -0,0 +1,244 @@
/**
* @file
* MQTT client
*/
/*
* Copyright (c) 2016 Erik Andersson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Andersson
*
*/
#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H
#define LWIP_HDR_APPS_MQTT_CLIENT_H
#include "lwip/apps/mqtt_opts.h"
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mqtt_client_t mqtt_client_t;
/** @ingroup mqtt
* Default MQTT port */
#define MQTT_PORT 1883
/*---------------------------------------------------------------------------------------------- */
/* Connection with server */
/**
* @ingroup mqtt
* Client information and connection parameters */
struct mqtt_connect_client_info_t {
/** Client identifier, must be set by caller */
const char *client_id;
/** User name and password, set to NULL if not used */
const char* client_user;
const char* client_pass;
/** keep alive time in seconds, 0 to disable keep alive functionality*/
u16_t keep_alive;
/** will topic, set to NULL if will is not to be used,
will_msg, will_qos and will retain are then ignored */
const char* will_topic;
const char* will_msg;
u8_t will_qos;
u8_t will_retain;
};
/**
* @ingroup mqtt
* Connection status codes */
typedef enum
{
MQTT_CONNECT_ACCEPTED = 0,
MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1,
MQTT_CONNECT_REFUSED_IDENTIFIER = 2,
MQTT_CONNECT_REFUSED_SERVER = 3,
MQTT_CONNECT_REFUSED_USERNAME_PASS = 4,
MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5,
MQTT_CONNECT_DISCONNECTED = 256,
MQTT_CONNECT_TIMEOUT = 257
} mqtt_connection_status_t;
/**
* @ingroup mqtt
* Function prototype for mqtt connection status callback. Called when
* client has connected to the server after initiating a mqtt connection attempt by
* calling mqtt_connect() or when connection is closed by server or an error
*
* @param client MQTT client itself
* @param arg Additional argument to pass to the callback function
* @param status Connect result code or disconnection notification @see mqtt_connection_status_t
*
*/
typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
/**
* @ingroup mqtt
* Data callback flags */
enum {
/** Flag set when last fragment of data arrives in data callback */
MQTT_DATA_FLAG_LAST = 1
};
/**
* @ingroup mqtt
* Function prototype for MQTT incoming publish data callback function. Called when data
* arrives to a subscribed topic @see mqtt_subscribe
*
* @param arg Additional argument to pass to the callback function
* @param data User data, pointed object, data may not be referenced after callback return,
NULL is passed when all publish data are delivered
* @param len Length of publish data fragment
* @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message
*
*/
typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags);
/**
* @ingroup mqtt
* Function prototype for MQTT incoming publish function. Called when an incoming publish
* arrives to a subscribed topic @see mqtt_subscribe
*
* @param arg Additional argument to pass to the callback function
* @param topic Zero terminated Topic text string, topic may not be referenced after callback return
* @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked
*/
typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len);
/**
* @ingroup mqtt
* Function prototype for mqtt request callback. Called when a subscribe, unsubscribe
* or publish request has completed
* @param arg Pointer to user data supplied when invoking request
* @param err ERR_OK on success
* ERR_TIMEOUT if no response was received within timeout,
* ERR_ABRT if (un)subscribe was denied
*/
typedef void (*mqtt_request_cb_t)(void *arg, err_t err);
/**
* Pending request item, binds application callback to pending server requests
*/
struct mqtt_request_t
{
/** Next item in list, NULL means this is the last in chain,
next pointing at itself means request is unallocated */
struct mqtt_request_t *next;
/** Callback to upper layer */
mqtt_request_cb_t cb;
void *arg;
/** MQTT packet identifier */
u16_t pkt_id;
/** Expire time relative to element before this */
u16_t timeout_diff;
};
/** Ring buffer */
struct mqtt_ringbuf_t {
u16_t put;
u16_t get;
u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE];
};
/** MQTT client */
struct mqtt_client_t
{
/** Timers and timeouts */
u16_t cyclic_tick;
u16_t keep_alive;
u16_t server_watchdog;
/** Packet identifier generator*/
u16_t pkt_id_seq;
/** Packet identifier of pending incoming publish */
u16_t inpub_pkt_id;
/** Connection state */
u8_t conn_state;
struct tcp_pcb *conn;
/** Connection callback */
void *connect_arg;
mqtt_connection_cb_t connect_cb;
/** Pending requests to server */
struct mqtt_request_t *pend_req_queue;
struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT];
void *inpub_arg;
/** Incoming data callback */
mqtt_incoming_data_cb_t data_cb;
mqtt_incoming_publish_cb_t pub_cb;
/** Input */
u32_t msg_idx;
u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN];
/** Output ring-buffer */
struct mqtt_ringbuf_t output;
};
/** Connect to server */
err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg,
const struct mqtt_connect_client_info_t *client_info);
/** Disconnect from server */
void mqtt_disconnect(mqtt_client_t *client);
/** Create new client */
mqtt_client_t *mqtt_client_new(void);
/** Check connection status */
u8_t mqtt_client_is_connected(mqtt_client_t *client);
/** Set callback to call for incoming publish */
void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t,
mqtt_incoming_data_cb_t data_cb, void *arg);
/** Common function for subscribe and unsubscribe */
err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub);
/** @ingroup mqtt
*Subscribe to topic */
#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1)
/** @ingroup mqtt
* Unsubscribe to topic */
#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0)
/** Publish data to topic */
err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
mqtt_request_cb_t cb, void *arg);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */

View File

@@ -0,0 +1,103 @@
/**
* @file
* MQTT client options
*/
/*
* Copyright (c) 2016 Erik Andersson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Andersson
*
*/
#ifndef LWIP_HDR_APPS_MQTT_OPTS_H
#define LWIP_HDR_APPS_MQTT_OPTS_H
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup mqtt_opts Options
* @ingroup mqtt
* @{
*/
/**
* Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads
*/
#ifndef MQTT_OUTPUT_RINGBUF_SIZE
#define MQTT_OUTPUT_RINGBUF_SIZE 256
#endif
/**
* Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8
* If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8
*/
#ifndef MQTT_VAR_HEADER_BUFFER_LEN
#define MQTT_VAR_HEADER_BUFFER_LEN 128
#endif
/**
* Maximum number of pending subscribe, unsubscribe and publish requests to server .
*/
#ifndef MQTT_REQ_MAX_IN_FLIGHT
#define MQTT_REQ_MAX_IN_FLIGHT 4
#endif
/**
* Seconds between each cyclic timer call.
*/
#ifndef MQTT_CYCLIC_TIMER_INTERVAL
#define MQTT_CYCLIC_TIMER_INTERVAL 5
#endif
/**
* Publish, subscribe and unsubscribe request timeout in seconds.
*/
#ifndef MQTT_REQ_TIMEOUT
#define MQTT_REQ_TIMEOUT 30
#endif
/**
* Seconds for MQTT connect response timeout after sending connect request
*/
#ifndef MQTT_CONNECT_TIMOUT
#define MQTT_CONNECT_TIMOUT 100
#endif
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */

View File

@@ -47,12 +47,67 @@
#include "arch/cc.h"
/**
* @defgroup compiler_abstraction Compiler/platform abstraction
* @ingroup sys_layer
* All defines related to this section must not be placed in lwipopts.h,
* but in arch/cc.h!
* These options cannot be \#defined in lwipopts.h since they are not options
* of lwIP itself, but options of the lwIP port to your system.
* @{
*/
/** Define the byte order of the system.
* Needed for conversion of network data to host byte order.
* Allowed values: LITTLE_ENDIAN and BIG_ENDIAN
*/
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
/** Define random number generator function of your system */
#ifdef __DOXYGEN__
#define LWIP_RAND() ((u32_t)rand())
#endif
/** Platform specific diagnostic output.\n
* Note the default implementation pulls in printf, which may
* in turn pull in a lot of standard libary code. In resource-constrained
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#include <stdio.h>
#include <stdlib.h>
#endif
/** Platform specific assertion handling.\n
* Note the default implementation pulls in printf, fflush and abort, which may
* in turn pull in a lot of standard libary code. In resource-constrained
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
#include <stdio.h>
#include <stdlib.h>
#endif
/** Define this to 1 in arch/cc.h of your port if you do not want to
* include stddef.h header to get size_t. You need to typedef size_t
* by yourself in this case.
*/
#ifndef LWIP_NO_STDDEF_H
#define LWIP_NO_STDDEF_H 0
#endif
#if !LWIP_NO_STDDEF_H
#include <stddef.h> /* for size_t */
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the stdint.h header. This cannot be \#defined in lwipopts.h since
* this is not an option of lwIP itself, but an option of the lwIP port
* to your system.
* Additionally, this header is meant to be \#included in lwipopts.h
* (you may need to declare function prototypes in there).
* the stdint.h header. You need to typedef the generic types listed in
* lwip/arch.h yourself in this case (u8_t, u16_t...).
*/
#ifndef LWIP_NO_STDINT_H
#define LWIP_NO_STDINT_H 0
@@ -71,11 +126,8 @@ typedef uintptr_t mem_ptr_t;
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the inttypes.h header. This cannot be \#defined in lwipopts.h since
* this is not an option of lwIP itself, but an option of the lwIP port
* to your system.
* Additionally, this header is meant to be \#included in lwipopts.h
* (you may need to declare function prototypes in there).
* the inttypes.h header. You need to define the format strings listed in
* lwip/arch.h yourself in this case (X8_F, U16_F...).
*/
#ifndef LWIP_NO_INTTYPES_H
#define LWIP_NO_INTTYPES_H 0
@@ -110,14 +162,44 @@ typedef uintptr_t mem_ptr_t;
#endif
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the limits.h header. You need to define the type limits yourself in this case
* (e.g. INT_MAX).
*/
#ifndef LWIP_NO_LIMITS_H
#define LWIP_NO_LIMITS_H 0
#endif
/* Include limits.h? */
#if !LWIP_NO_LIMITS_H
#include <limits.h>
#endif
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
#ifndef LWIP_CONST_CAST
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
#endif
/** Get rid of alignment cast warnings (GCC -Wcast-align) */
#ifndef LWIP_ALIGNMENT_CAST
#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
#endif
/** Get rid of warnings related to pointer-to-numeric and vice-versa casts,
* e.g. "conversion from 'u8_t' to 'void *' of greater size"
*/
#ifndef LWIP_PTR_NUMERIC_CAST
#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
#endif
/** Allocates a memory buffer of specified size that is of sufficient size to align
* its start address using LWIP_MEM_ALIGN.
* You can declare your own version here e.g. to enforce alignment without adding
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
* requirements.
* e.g. if you use gcc and need 32 bit alignment:
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] __attribute__((aligned(4)))
* or more portable:
* requirements.\n
* e.g. if you use gcc and need 32 bit alignment:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
* or more portable:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
*/
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
@@ -151,39 +233,84 @@ typedef uintptr_t mem_ptr_t;
extern "C" {
#endif
/** Packed structs support.
* Placed BEFORE declaration of a packed struct.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_BEGIN
#define PACK_STRUCT_BEGIN
#endif /* PACK_STRUCT_BEGIN */
/** Packed structs support.
* Placed AFTER declaration of a packed struct.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_END
#define PACK_STRUCT_END
#endif /* PACK_STRUCT_END */
/** Packed structs support.
* Placed between end of declaration of a packed struct and trailing semicolon.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_STRUCT
#if defined(__GNUC__) || defined(__clang__)
#define PACK_STRUCT_STRUCT __attribute__((packed))
#else
#define PACK_STRUCT_STRUCT
#endif
#endif /* PACK_STRUCT_STRUCT */
/** Packed structs support.
* Wraps u32_t and u16_t members.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FIELD
#define PACK_STRUCT_FIELD(x) x
#endif /* PACK_STRUCT_FIELD */
/* Used for struct fields of u8_t,
* where some compilers warn that packing is not necessary */
/** Packed structs support.
* Wraps u8_t members, where some compilers warn that packing is not necessary.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FLD_8
#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x)
#endif /* PACK_STRUCT_FLD_8 */
/* Used for struct fields of that are packed structs themself,
* where some compilers warn that packing is not necessary */
/** Packed structs support.
* Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FLD_S
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
#endif /* PACK_STRUCT_FLD_S */
/** Packed structs support using \#include files before and after struct to be packed.\n
* The file included BEFORE the struct is "arch/bpstruct.h".\n
* The file included AFTER the struct is "arch/epstruct.h".\n
* This can be used to implement struct packing on MS Visual C compilers, see
* the Win32 port in the lwIP contrib repository for reference.
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifdef __DOXYGEN__
#define PACK_STRUCT_USE_INCLUDES
#endif
/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */
#ifndef LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x) (void)x
#endif /* LWIP_UNUSED_ARG */
/**
* @}
*/
#ifdef __cplusplus
}

View File

@@ -88,6 +88,8 @@ u8_t autoip_supplied_address(const struct netif *netif);
/* for lwIP internal use by ip4.c */
u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr);
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
#ifdef __cplusplus
}
#endif

View File

@@ -40,24 +40,45 @@
#include "lwip/arch.h"
#include "lwip/opt.h"
/** lower two bits indicate debug level
* - 0 all
* - 1 warning
* - 2 serious
* - 3 severe
/**
* @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values
* @ingroup lwip_opts_debugmsg
* @{
*/
#define LWIP_DBG_LEVEL_ALL 0x00
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */
#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SEVERE 0x03
#define LWIP_DBG_MASK_LEVEL 0x03
/** @name Debug level (LWIP_DBG_MIN_LEVEL)
* @{
*/
/** Debug level: ALL messages*/
#define LWIP_DBG_LEVEL_ALL 0x00
/** Debug level: Warnings. bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_WARNING 0x01
/** Debug level: Serious. memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02
/** Debug level: Severe */
#define LWIP_DBG_LEVEL_SEVERE 0x03
/**
* @}
*/
#define LWIP_DBG_MASK_LEVEL 0x03
/* compatibility define only */
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL
/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON)
* @{
*/
/** flag for LWIP_DEBUGF to enable that debug message */
#define LWIP_DBG_ON 0x80U
/** flag for LWIP_DEBUGF to disable that debug message */
#define LWIP_DBG_OFF 0x00U
/**
* @}
*/
/** @name Debug message types (LWIP_DBG_TYPES_ON)
* @{
*/
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
#define LWIP_DBG_TRACE 0x40U
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
@@ -66,11 +87,31 @@
#define LWIP_DBG_FRESH 0x10U
/** flag for LWIP_DEBUGF to halt after printing this debug message */
#define LWIP_DBG_HALT 0x08U
/**
* @}
*/
/**
* LWIP_NOASSERT: Disable LWIP_ASSERT checks.
* -- To disable assertions define LWIP_NOASSERT in arch/cc.h.
* @}
*/
/**
* @defgroup lwip_assertions Assertion handling
* @ingroup lwip_opts_debug
* @{
*/
/**
* LWIP_NOASSERT: Disable LWIP_ASSERT checks:
* To disable assertions define LWIP_NOASSERT in arch/cc.h.
*/
#ifdef __DOXYGEN__
#define LWIP_NOASSERT
#undef LWIP_NOASSERT
#endif
/**
* @}
*/
#ifndef LWIP_NOASSERT
#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \
LWIP_PLATFORM_ASSERT(message); }} while(0)
@@ -81,7 +122,6 @@
#define LWIP_ASSERT(message, assertion)
#endif /* LWIP_NOASSERT */
/** if "expression" isn't true, then print "message" and execute "handler" expression */
#ifndef LWIP_ERROR
#ifndef LWIP_NOASSERT
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
@@ -91,17 +131,23 @@
#define LWIP_PLATFORM_ERROR(message)
#endif
/* if "expression" isn't true, then print "message" and execute "handler" expression */
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
LWIP_PLATFORM_ERROR(message); handler;}} while(0)
#endif /* LWIP_ERROR */
/** Enable debug message printing, but only if debug message type is enabled
* AND is of correct type AND is at least LWIP_DBG_LEVEL.
*/
#ifdef __DOXYGEN__
#define LWIP_DEBUG
#undef LWIP_DEBUG
#endif
#ifdef LWIP_DEBUG
#ifndef LWIP_PLATFORM_DIAG
#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h"
#endif
/** print debug message only if debug message type is enabled...
* AND is of correct type AND is at least LWIP_DBG_LEVEL
*/
#define LWIP_DEBUGF(debug, message) do { \
if ( \
((debug) & LWIP_DBG_ON) && \
@@ -119,4 +165,3 @@
#endif /* LWIP_DEBUG */
#endif /* LWIP_HDR_DEBUG_H */

View File

@@ -57,6 +57,12 @@ extern "C" {
/* Get the number of entries in an array ('x' must NOT be a pointer!) */
#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
/** Create u32_t value from bytes */
#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \
((u32_t)((b) & 0xff) << 16) | \
((u32_t)((c) & 0xff) << 8) | \
(u32_t)((d) & 0xff))
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
@@ -65,13 +71,6 @@ extern "C" {
#endif
#endif
/* Endianess-optimized shifting of two u8_t to create one u16_t */
#if BYTE_ORDER == LITTLE_ENDIAN
#define LWIP_MAKE_U16(a, b) ((a << 8) | b)
#else
#define LWIP_MAKE_U16(a, b) ((b << 8) | a)
#endif
#if BYTE_ORDER == BIG_ENDIAN
#define lwip_htons(x) (x)
#define lwip_ntohs(x) (x)
@@ -103,11 +102,11 @@ u32_t lwip_htonl(u32_t x);
/* These macros should be calculated by the preprocessor and are used
with compile-time constants only (so that there is no little-endian
overhead at runtime). */
#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
#define PP_NTOHS(x) PP_HTONS(x)
#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
(((x) & 0xff00) << 8) | \
(((x) & 0xff0000UL) >> 8) | \
#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#define PP_NTOHL(x) PP_HTONL(x)

View File

@@ -132,6 +132,8 @@ void dhcp_fine_tmr(void);
extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
#endif /* LWIP_DHCP_GET_NTP_SRV */
#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
#ifdef __cplusplus
}
#endif

View File

@@ -61,7 +61,7 @@ extern "C" {
#ifndef LWIP_DNS_ADDRTYPE_DEFAULT
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6
#endif
#elif defined(LWIP_IPV4)
#elif LWIP_IPV4
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4
#else
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6
@@ -76,6 +76,7 @@ struct local_hostlist_entry {
ip_addr_t addr;
struct local_hostlist_entry *next;
};
#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL}
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
@@ -84,6 +85,13 @@ struct local_hostlist_entry {
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
#endif /* DNS_LOCAL_HOSTLIST */
#if LWIP_IPV4
extern const ip_addr_t dns_mquery_v4group;
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
extern const ip_addr_t dns_mquery_v6group;
#endif /* LWIP_IPV6 */
/** Callback which is invoked when a hostname is found.
* A function of this type must be implemented by the application using the DNS resolver.
* @param name pointer to the name that was looked up.
@@ -104,10 +112,14 @@ err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *add
u8_t dns_addrtype);
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
#if DNS_LOCAL_HOSTLIST
size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg);
err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype);
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
#endif /* DNS_LOCAL_HOSTLIST */
#ifdef __cplusplus
}

View File

@@ -45,100 +45,100 @@ extern "C" {
#ifdef LWIP_PROVIDE_ERRNO
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */

View File

@@ -69,7 +69,7 @@ enum icmp_dur_type {
/** ICMP time exceeded codes */
enum icmp_te_type {
/* time to live exceeded in transit */
/** time to live exceeded in transit */
ICMP_TE_TTL = 0,
/** fragment reassembly time exceeded */
ICMP_TE_FRAG = 1

View File

@@ -45,99 +45,12 @@
#include "lwip/pbuf.h"
#include "lwip/ip6_addr.h"
#include "lwip/netif.h"
#include "lwip/prot/icmp6.h"
#ifdef __cplusplus
extern "C" {
#endif
/** ICMP type */
enum icmp6_type {
/** Destination unreachable */
ICMP6_TYPE_DUR = 1,
/** Packet too big */
ICMP6_TYPE_PTB = 2,
/** Time exceeded */
ICMP6_TYPE_TE = 3,
/** Parameter problem */
ICMP6_TYPE_PP = 4,
/** Private experimentation */
ICMP6_TYPE_PE1 = 100,
/** Private experimentation */
ICMP6_TYPE_PE2 = 101,
/** Reserved for expansion of error messages */
ICMP6_TYPE_RSV_ERR = 127,
/** Echo request */
ICMP6_TYPE_EREQ = 128,
/** Echo reply */
ICMP6_TYPE_EREP = 129,
/** Multicast listener query */
ICMP6_TYPE_MLQ = 130,
/** Multicast listener report */
ICMP6_TYPE_MLR = 131,
/** Multicast listener done */
ICMP6_TYPE_MLD = 132,
/** Router solicitation */
ICMP6_TYPE_RS = 133,
/** Router advertisement */
ICMP6_TYPE_RA = 134,
/** Neighbor solicitation */
ICMP6_TYPE_NS = 135,
/** Neighbor advertisement */
ICMP6_TYPE_NA = 136,
/** Redirect */
ICMP6_TYPE_RD = 137,
/** Multicast router advertisement */
ICMP6_TYPE_MRA = 151,
/** Multicast router solicitation */
ICMP6_TYPE_MRS = 152,
/** Multicast router termination */
ICMP6_TYPE_MRT = 153,
/** Private experimentation */
ICMP6_TYPE_PE3 = 200,
/** Private experimentation */
ICMP6_TYPE_PE4 = 201,
/** Reserved for expansion of informational messages */
ICMP6_TYPE_RSV_INF = 255
};
/** ICMP destination unreachable codes */
enum icmp6_dur_code {
/** No route to destination */
ICMP6_DUR_NO_ROUTE = 0,
/** Communication with destination administratively prohibited */
ICMP6_DUR_PROHIBITED = 1,
/** Beyond scope of source address */
ICMP6_DUR_SCOPE = 2,
/** Address unreachable */
ICMP6_DUR_ADDRESS = 3,
/** Port unreachable */
ICMP6_DUR_PORT = 4,
/** Source address failed ingress/egress policy */
ICMP6_DUR_POLICY = 5,
/** Reject route to destination */
ICMP6_DUR_REJECT_ROUTE = 6
};
/** ICMP time exceeded codes */
enum icmp6_te_code {
/** Hop limit exceeded in transit */
ICMP6_TE_HL = 0,
/** Fragment reassembly time exceeded */
ICMP6_TE_FRAG = 1
};
/** ICMP parameter code */
enum icmp6_pp_code {
/** Erroneous header field encountered */
ICMP6_PP_FIELD = 0,
/** Unrecognized next header type encountered */
ICMP6_PP_HEADER = 1,
/** Unrecognized IPv6 option encountered */
ICMP6_PP_OPTION = 2
};
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
void icmp6_input(struct pbuf *p, struct netif *inp);

View File

@@ -132,10 +132,10 @@ extern const struct in6_addr in6addr_any;
#if LWIP_IPV4
#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */
#define inet_addr_to_ipaddr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr))
#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr))
/* directly map this to the lwip internal functions */
#define inet_addr(cp) ipaddr_addr(cp)

View File

@@ -54,11 +54,11 @@ extern "C" {
/** x.X.x: Minor version of the stack */
#define LWIP_VERSION_MINOR 0
/** x.x.X: Revision of the stack */
#define LWIP_VERSION_REVISION 0
#define LWIP_VERSION_REVISION 2
/** 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) */
#define LWIP_VERSION_RC 0
#define LWIP_VERSION_RC LWIP_RC_RELEASE
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
#define LWIP_RC_RELEASE 255

View File

@@ -52,24 +52,9 @@ struct ip4_addr {
u32_t addr;
};
/** This is the packed version of ip4_addr_t,
used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip4_addr_packed {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** ip4_addr_t uses a struct for convenience only, so that the same defines can
* operate both on ip4_addr_t as well as on ip4_addr_p_t. */
typedef struct ip4_addr ip4_addr_t;
typedef struct ip4_addr_packed ip4_addr_p_t;
/**
* struct ipaddr2 is used in the definition of the ARP packet format in
@@ -131,23 +116,8 @@ struct netif;
#define IP_LOOPBACKNET 127 /* official! */
#if BYTE_ORDER == BIG_ENDIAN
/** Set an IP address given by the four byte-parts */
#define IP4_ADDR(ipaddr, a,b,c,d) \
(ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
((u32_t)((b) & 0xff) << 16) | \
((u32_t)((c) & 0xff) << 8) | \
(u32_t)((d) & 0xff)
#else
/** Set an IP address given by the four byte-parts.
Little-endian version that prevents the use of lwip_htonl. */
#define IP4_ADDR(ipaddr, a,b,c,d) \
(ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
((u32_t)((c) & 0xff) << 16) | \
((u32_t)((b) & 0xff) << 8) | \
(u32_t)((a) & 0xff)
#endif
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d))
/** MEMCPY-like copying of IP addresses where addresses are known to be
* 16-bit-aligned if the port is correctly configured (so a port could define

View File

@@ -43,6 +43,7 @@
#define LWIP_HDR_IP6_ADDR_H
#include "lwip/opt.h"
#include "def.h"
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
@@ -58,41 +59,12 @@ struct ip6_addr {
u32_t addr[4];
};
/** This is the packed version of ip6_addr_t,
used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip6_addr_packed {
PACK_STRUCT_FIELD(u32_t addr[4]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** IPv6 address */
typedef struct ip6_addr ip6_addr_t;
typedef struct ip6_addr_packed ip6_addr_p_t;
#if BYTE_ORDER == BIG_ENDIAN
/** Set an IPv6 partial address given by byte-parts. */
/** Set an IPv6 partial address given by byte-parts */
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
(ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \
((u32_t)((b) & 0xff) << 16) | \
((u32_t)((c) & 0xff) << 8) | \
(u32_t)((d) & 0xff)
#else
/** Set an IPv6 partial address given by byte-parts.
Little-endian version, stored in network order (no lwip_htonl). */
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
(ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \
((u32_t)((c) & 0xff) << 16) | \
((u32_t)((b) & 0xff) << 8) | \
(u32_t)((a) & 0xff)
#endif
(ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d))
/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order
(use PP_HTONL() for constants) */
@@ -187,7 +159,7 @@ Little-endian version, stored in network order (no lwip_htonl). */
#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL))
#define ip6_addr_isipv6mappedipv4(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL)))
#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL)))
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL))
#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))

View File

@@ -66,7 +66,7 @@ enum lwip_ip_addr_type {
* A union struct for both IP version's addresses.
* ATTENTION: watch out for its size when adding IPv6 address scope!
*/
typedef struct _ip_addr {
typedef struct ip_addr {
union {
ip6_addr_t ip6;
ip4_addr_t ip4;
@@ -79,8 +79,12 @@ extern const ip_addr_t ip_addr_any_type;
/** @ingroup ip4addr */
#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 }
/** @ingroup ip4addr */
#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d)))
/** @ingroup ip6addr */
#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 }
/** @ingroup ip6addr */
#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 }
/** @ingroup ipaddr */
#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY)
@@ -118,6 +122,8 @@ extern const ip_addr_t ip_addr_any_type;
/** @ingroup ip6addr */
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \
IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0)
/** @ingroup ip6addr */
#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3))
/** @ingroup ipaddr */
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
@@ -215,6 +221,19 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
/** @ingroup ipaddr */
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
/** @ingroup ipaddr */
#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \
(ip6addr)->addr[3] = (ip4addr)->addr; \
(ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \
(ip6addr)->addr[1] = 0; \
(ip6addr)->addr[0] = 0; } while(0);
/** @ingroup ipaddr */
#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \
(ip4addr)->addr = (ip6addr)->addr[3];
#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY)
#else /* LWIP_IPV4 && LWIP_IPV6 */
#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1
@@ -224,6 +243,7 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
typedef ip4_addr_t ip_addr_t;
#define IPADDR4_INIT(u32val) { u32val }
#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d)))
#define IP_IS_V4_VAL(ipaddr) 1
#define IP_IS_V6_VAL(ipaddr) 0
#define IP_IS_V4(ipaddr) 1
@@ -263,10 +283,13 @@ typedef ip4_addr_t ip_addr_t;
#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX
#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY)
#else /* LWIP_IPV4 */
typedef ip6_addr_t ip_addr_t;
#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } }
#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } }
#define IP_IS_V4_VAL(ipaddr) 0
#define IP_IS_V6_VAL(ipaddr) 1
#define IP_IS_V4(ipaddr) 0
@@ -277,6 +300,7 @@ typedef ip6_addr_t ip_addr_t;
#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6
#define ip_2_ip6(ipaddr) (ipaddr)
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3)
#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3))
#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src)
#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src)
@@ -304,6 +328,8 @@ typedef ip6_addr_t ip_addr_t;
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY)
#endif /* LWIP_IPV4 */
#endif /* LWIP_IPV4 && LWIP_IPV6 */
@@ -314,7 +340,13 @@ extern const ip_addr_t ip_addr_broadcast;
/**
* @ingroup ip4addr
* Provided for compatibility. Use IP4_ADDR_ANY for better readability.
* Can be used as a fixed/const ip_addr_t
* for the IP wildcard.
* Defined to @ref IP4_ADDR_ANY when IPv4 is enabled.
* Defined to @ref IP6_ADDR_ANY in IPv6 only systems.
* Use this if you can handle IPv4 _AND_ IPv6 addresses.
* Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP
* type matters.
*/
#define IP_ADDR_ANY IP4_ADDR_ANY
/**
@@ -355,7 +387,7 @@ extern const ip_addr_t ip6_addr_any;
#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any))
#if !LWIP_IPV4
/** Just a little upgrade-helper for IPv6-only configurations: */
/** IPv6-only configurations */
#define IP_ADDR_ANY IP6_ADDR_ANY
#endif /* !LWIP_IPV4 */

View File

@@ -45,7 +45,8 @@ extern "C" {
#if MEM_LIBC_MALLOC
#include <stddef.h> /* for size_t */
#include "lwip/arch.h"
typedef size_t mem_size_t;
#define MEM_SIZE_F SZT_F

View File

@@ -48,107 +48,32 @@
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
#include "lwip/pbuf.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include "lwip/netif.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Struct for tables. */
struct nd6_neighbor_cache_entry {
ip6_addr_t next_hop_address;
struct netif *netif;
u8_t lladdr[NETIF_MAX_HWADDR_LEN];
/*u32_t pmtu;*/
#if LWIP_ND6_QUEUEING
/** Pointer to queue of pending outgoing packets on this entry. */
struct nd6_q_entry *q;
#else /* LWIP_ND6_QUEUEING */
/** Pointer to a single pending outgoing packet on this entry. */
struct pbuf *q;
#endif /* LWIP_ND6_QUEUEING */
u8_t state;
u8_t isrouter;
union {
u32_t reachable_time; /* in ms since value may originate from network packet */
u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */
u32_t probes_sent;
u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */
} counter;
};
struct nd6_destination_cache_entry {
ip6_addr_t destination_addr;
ip6_addr_t next_hop_addr;
u16_t pmtu;
u32_t age;
};
struct nd6_prefix_list_entry {
ip6_addr_t prefix;
struct netif *netif;
u32_t invalidation_timer; /* in ms since value may originate from network packet */
#if LWIP_IPV6_AUTOCONFIG
u8_t flags;
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
#endif /* LWIP_IPV6_AUTOCONFIG */
};
struct nd6_router_list_entry {
struct nd6_neighbor_cache_entry *neighbor_entry;
u32_t invalidation_timer; /* in ms since value may originate from network packet */
u8_t flags;
};
enum nd6_neighbor_cache_entry_state {
ND6_NO_ENTRY = 0,
ND6_INCOMPLETE,
ND6_REACHABLE,
ND6_STALE,
ND6_DELAY,
ND6_PROBE
};
#if LWIP_ND6_QUEUEING
/** struct for queueing outgoing packets for unknown address
* defined here to be accessed by memp.h
*/
struct nd6_q_entry {
struct nd6_q_entry *next;
struct pbuf *p;
};
#endif /* LWIP_ND6_QUEUEING */
/** 1 second period */
#define ND6_TMR_INTERVAL 1000
/* Router tables. */
/* @todo make these static? and entries accessible through API? */
extern struct nd6_neighbor_cache_entry neighbor_cache[];
extern struct nd6_destination_cache_entry destination_cache[];
extern struct nd6_prefix_list_entry prefix_list[];
extern struct nd6_router_list_entry default_router_list[];
/* Default values, can be updated by a RA message. */
extern u32_t reachable_time;
extern u32_t retrans_timer;
struct pbuf;
struct netif;
void nd6_tmr(void);
void nd6_input(struct pbuf *p, struct netif *inp);
s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
void nd6_clear_destination_cache(void);
struct netif *nd6_find_route(const ip6_addr_t *ip6addr);
err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp);
u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif);
err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *p);
#if LWIP_ND6_TCP_REACHABILITY_HINTS
void nd6_reachability_hint(const ip6_addr_t *ip6addr);
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
void nd6_cleanup_netif(struct netif *netif);
#if LWIP_IPV6_MLD
void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state);
#endif /* LWIP_IPV6_MLD */
#ifdef __cplusplus
}

View File

@@ -38,8 +38,7 @@
#if LWIP_DNS && LWIP_SOCKET
#include <stddef.h> /* for size_t */
#include "lwip/arch.h"
#include "lwip/inet.h"
#include "lwip/sockets.h"

View File

@@ -93,13 +93,17 @@ err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
netifapi_errt_fn errtfunc);
/** @ingroup netifapi_netif */
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
/** @ingroup netifapi_netif */
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
/** @ingroup netifapi_netif */
#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL)
#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL)
/** @ingroup netifapi_netif */
#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL)
#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL)
/** @ingroup netifapi_netif */
#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL)
/** @ingroup netifapi_netif */
#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL)
/**
* @defgroup netifapi_dhcp4 DHCPv4

View File

@@ -882,6 +882,15 @@
#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__
#define LWIP_DHCP_MAX_NTP_SERVERS 1
#endif
/**
* LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select.
* DHCP servers received in the response are passed to DNS via @ref dns_setserver()
* (up to the maximum limit defined here).
*/
#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__
#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS
#endif
/**
* @}
*/
@@ -1038,11 +1047,9 @@
#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2
#define LWIP_DNS_SECURE_RAND_SRC_PORT 4
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled,
* you have to define
* \#define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}}
* (an array of structs name/address, where address is an u32_t in network
* byte order).
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer:
* \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \
* DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)}
*
* Instead, you can also use an external function:
* \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
@@ -1057,6 +1064,12 @@
#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__
#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
/** Set this to 1 to enable querying ".local" names via mDNS
* using a One-Shot Multicast DNS Query */
#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__
#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0
#endif
/**
* @}
*/
@@ -1128,7 +1141,10 @@
/**
* TCP_WND: The size of a TCP window. This must be at least
* (2 * TCP_MSS) for things to work well
* (2 * TCP_MSS) for things to work well.
* ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size
* with scaling applied. Maximum window value in the TCP header
* will be TCP_WND >> TCP_RCV_SCALE
*/
#if !defined TCP_WND || defined __DOXYGEN__
#define TCP_WND (4 * TCP_MSS)
@@ -1345,7 +1361,7 @@
* for an additional encapsulation header before ethernet headers (e.g. 802.11)
*/
#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__
#define PBUF_LINK_ENCAPSULATION_HLEN 0
#define PBUF_LINK_ENCAPSULATION_HLEN 0u
#endif
/**
@@ -2161,7 +2177,7 @@
/**
* LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
*/
#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ || defined __DOXYGEN__
#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__
#define LWIP_IPV6_REASS (LWIP_IPV6)
#endif
@@ -2227,13 +2243,18 @@
*/
/**
* LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol.
* If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must
* indiscriminately pass all inbound IPv6 multicast traffic to lwIP.
*/
#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__
#define LWIP_IPV6_MLD (LWIP_IPV6)
#endif
/**
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined.
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined.
* There must be enough groups so that each netif can join the solicited-node
* multicast group for each of its local addresses, plus one for MDNS if
* applicable, plus any number of groups to be joined on UDP sockets.
*/
#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__
#define MEMP_NUM_MLD6_GROUP 4
@@ -2339,7 +2360,7 @@
* LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation
* message is sent, during neighbor reachability detection.
*/
#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__s
#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000
#endif
@@ -2356,9 +2377,18 @@
* with reachability hints for connected destinations. This helps avoid sending
* unicast neighbor solicitation messages.
*/
#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ || defined __DOXYGEN__
#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__
#define LWIP_ND6_TCP_REACHABILITY_HINTS 1
#endif
/**
* LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive
* DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS
* servers to the DNS module.
*/
#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__
#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0
#endif
/**
* @}
*/
@@ -2383,6 +2413,38 @@
* @{
*/
/**
* LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks.
* Declare your hook function prototypes in there, you may also #include all headers
* providing data types that are need in this file.
*/
#ifdef __DOXYGEN__
#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h"
#endif
/**
* LWIP_HOOK_TCP_ISN:
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP
* connection. The default lwIP ISN generation algorithm is very basic and may
* allow for TCP spoofing attacks. This hook provides the means to implement
* the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn),
* or any other desired algorithm as a replacement.
* Called from tcp_connect() and tcp_listen_input() when an ISN is needed for
* a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n
* Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port);
* - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n
* Arguments:
* - local_ip: pointer to the local IP address of the connection
* - local_port: local port number of the connection (host-byte order)
* - remote_ip: pointer to the remote IP address of the connection
* - remote_port: remote port number of the connection (host-byte order)\n
* Return value:
* - the 32-bit Initial Sequence Number to use for the new TCP connection.
*/
#ifdef __DOXYGEN__
#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port)
#endif
/**
* LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
* - called from ip_input() (IPv4)
@@ -2424,7 +2486,7 @@
* - dest: the destination IPv4 address
* Returns the IPv4 address of the gateway to handle the specified destination
* IPv4 address. If NULL is returned, the netif's default gateway is used.
* The returned address MUST be reachable on the specified netif!
* The returned address MUST be directly reachable on the specified netif!
* This function is meant to implement advanced IPv4 routing together with
* LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is
* not part of lwIP but can e.g. be hidden in the netif's state argument.
@@ -2460,6 +2522,22 @@
#define LWIP_HOOK_IP6_ROUTE(src, dest)
#endif
/**
* LWIP_HOOK_ND6_GET_GW(netif, dest):
* - called from nd6_get_next_hop_entry() (IPv6)
* - netif: the netif used for sending
* - dest: the destination IPv6 address
* Returns the IPv6 address of the next hop to handle the specified destination
* IPv6 address. If NULL is returned, a NDP-discovered router is used instead.
* The returned address MUST be directly reachable on the specified netif!
* This function is meant to implement advanced IPv6 routing together with
* LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is
* not part of lwIP but can e.g. be hidden in the netif's state argument.
*/
#ifdef __DOXYGEN__
#define LWIP_HOOK_ND6_GET_GW(netif, dest)
#endif
/**
* LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr):
* - called from ethernet_input() if VLAN support is enabled
@@ -2523,7 +2601,7 @@
---------------------------------------
*/
/**
* @defgroup lwip_opts_debugmsg Debugging
* @defgroup lwip_opts_debugmsg Debug messages
* @ingroup lwip_opts_debug
* @{
*/
@@ -2531,14 +2609,16 @@
* LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is
* compared against this value. If it is smaller, then debugging
* messages are written.
* @see debugging_levels
*/
#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ || defined __DOXYGEN__
#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
#endif
/**
* LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable
* debug messages of certain types.
* @see debugging_levels
*/
#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON

View File

@@ -43,8 +43,7 @@
/* Note: Netconn API is always available when sockets are enabled -
* sockets are implemented on top of them */
#include <stddef.h> /* for size_t */
#include "lwip/arch.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#include "lwip/sys.h"

View File

@@ -0,0 +1,144 @@
/**
* @file
*
* Neighbor discovery and stateless address autoconfiguration for IPv6.
* Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
* (Address autoconfiguration).
*/
/*
* Copyright (c) 2010 Inico Technologies Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Ivan Delamer <delamer@inicotech.com>
*
*
* Please coordinate changes and requests with Ivan Delamer
* <delamer@inicotech.com>
*/
#ifndef LWIP_HDR_ND6_PRIV_H
#define LWIP_HDR_ND6_PRIV_H
#include "lwip/opt.h"
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
#include "lwip/pbuf.h"
#include "lwip/ip6_addr.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_ND6_QUEUEING
/** struct for queueing outgoing packets for unknown address
* defined here to be accessed by memp.h
*/
struct nd6_q_entry {
struct nd6_q_entry *next;
struct pbuf *p;
};
#endif /* LWIP_ND6_QUEUEING */
/** Struct for tables. */
struct nd6_neighbor_cache_entry {
ip6_addr_t next_hop_address;
struct netif *netif;
u8_t lladdr[NETIF_MAX_HWADDR_LEN];
/*u32_t pmtu;*/
#if LWIP_ND6_QUEUEING
/** Pointer to queue of pending outgoing packets on this entry. */
struct nd6_q_entry *q;
#else /* LWIP_ND6_QUEUEING */
/** Pointer to a single pending outgoing packet on this entry. */
struct pbuf *q;
#endif /* LWIP_ND6_QUEUEING */
u8_t state;
u8_t isrouter;
union {
u32_t reachable_time; /* in ms since value may originate from network packet */
u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */
u32_t probes_sent;
u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */
} counter;
};
struct nd6_destination_cache_entry {
ip6_addr_t destination_addr;
ip6_addr_t next_hop_addr;
u16_t pmtu;
u32_t age;
};
struct nd6_prefix_list_entry {
ip6_addr_t prefix;
struct netif *netif;
u32_t invalidation_timer; /* in ms since value may originate from network packet */
#if LWIP_IPV6_AUTOCONFIG
u8_t flags;
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
#endif /* LWIP_IPV6_AUTOCONFIG */
};
struct nd6_router_list_entry {
struct nd6_neighbor_cache_entry *neighbor_entry;
u32_t invalidation_timer; /* in ms since value may originate from network packet */
u8_t flags;
};
enum nd6_neighbor_cache_entry_state {
ND6_NO_ENTRY = 0,
ND6_INCOMPLETE,
ND6_REACHABLE,
ND6_STALE,
ND6_DELAY,
ND6_PROBE
};
/* Router tables. */
/* @todo make these static? and entries accessible through API? */
extern struct nd6_neighbor_cache_entry neighbor_cache[];
extern struct nd6_destination_cache_entry destination_cache[];
extern struct nd6_prefix_list_entry prefix_list[];
extern struct nd6_router_list_entry default_router_list[];
/* Default values, can be updated by a RA message. */
extern u32_t reachable_time;
extern u32_t retrans_timer;
#ifdef __cplusplus
}
#endif
#endif /* LWIP_IPV6 */
#endif /* LWIP_HDR_ND6_PRIV_H */

View File

@@ -34,8 +34,8 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_TCP_IMPL_H
#define LWIP_HDR_TCP_IMPL_H
#ifndef LWIP_HDR_TCP_PRIV_H
#define LWIP_HDR_TCP_PRIV_H
#include "lwip/opt.h"
@@ -170,16 +170,18 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
LWIP_EVENT_RECV, NULL, 0, ERR_OK)
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_CONNECTED, NULL, 0, (err))
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
LWIP_EVENT_ERR, NULL, 0, (err))
#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \
ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \
} else { \
ret = ERR_ARG; } } while(0)
#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \
lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0)
#else /* LWIP_EVENT_API */
#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \
do { \
if((lpcb != NULL) && ((lpcb)->accept != NULL)) \
if((lpcb)->accept != NULL) \
(ret) = (lpcb)->accept((arg),(pcb),(err)); \
else (ret) = ERR_ARG; \
} while (0)
@@ -223,8 +225,9 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
else (ret) = ERR_OK; \
} while (0)
#define TCP_EVENT_ERR(errf,arg,err) \
#define TCP_EVENT_ERR(last_state,errf,arg,err) \
do { \
LWIP_UNUSED_ARG(last_state); \
if((errf) != NULL) \
(errf)((arg),(err)); \
} while (0)
@@ -249,7 +252,7 @@ struct tcp_seg {
#if TCP_OVERSIZE_DBGCHECK
u16_t oversize_left; /* Extra bytes available at the end of the last
pbuf in unsent (used for asserting vs.
tcp_pcb.unsent_oversized only) */
tcp_pcb.unsent_oversize only) */
#endif /* TCP_OVERSIZE_DBGCHECK */
#if TCP_CHECKSUM_ON_COPY
u16_t chksum;
@@ -452,7 +455,7 @@ void tcp_rst(u32_t seqno, u32_t ackno,
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
u16_t local_port, u16_t remote_port);
u32_t tcp_next_iss(void);
u32_t tcp_next_iss(struct tcp_pcb *pcb);
err_t tcp_keepalive(struct tcp_pcb *pcb);
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
@@ -501,4 +504,4 @@ void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_a
#endif /* LWIP_TCP */
#endif /* LWIP_HDR_TCP_H */
#endif /* LWIP_HDR_TCP_PRIV_H */

View File

@@ -115,6 +115,24 @@ PACK_STRUCT_END
#endif
#define SIZEOF_DNS_HDR 12
/* Multicast DNS definitions */
/** UDP port for multicast DNS queries */
#ifndef DNS_MQUERY_PORT
#define DNS_MQUERY_PORT 5353
#endif
/* IPv4 group for multicast DNS queries: 224.0.0.251 */
#ifndef DNS_MQUERY_IPV4_GROUP_INIT
#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251)
#endif
/* IPv6 group for multicast DNS queries: FF02::FB */
#ifndef DNS_MQUERY_IPV6_GROUP_INIT
#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB)
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -43,6 +43,93 @@
extern "C" {
#endif
/** ICMP type */
enum icmp6_type {
/** Destination unreachable */
ICMP6_TYPE_DUR = 1,
/** Packet too big */
ICMP6_TYPE_PTB = 2,
/** Time exceeded */
ICMP6_TYPE_TE = 3,
/** Parameter problem */
ICMP6_TYPE_PP = 4,
/** Private experimentation */
ICMP6_TYPE_PE1 = 100,
/** Private experimentation */
ICMP6_TYPE_PE2 = 101,
/** Reserved for expansion of error messages */
ICMP6_TYPE_RSV_ERR = 127,
/** Echo request */
ICMP6_TYPE_EREQ = 128,
/** Echo reply */
ICMP6_TYPE_EREP = 129,
/** Multicast listener query */
ICMP6_TYPE_MLQ = 130,
/** Multicast listener report */
ICMP6_TYPE_MLR = 131,
/** Multicast listener done */
ICMP6_TYPE_MLD = 132,
/** Router solicitation */
ICMP6_TYPE_RS = 133,
/** Router advertisement */
ICMP6_TYPE_RA = 134,
/** Neighbor solicitation */
ICMP6_TYPE_NS = 135,
/** Neighbor advertisement */
ICMP6_TYPE_NA = 136,
/** Redirect */
ICMP6_TYPE_RD = 137,
/** Multicast router advertisement */
ICMP6_TYPE_MRA = 151,
/** Multicast router solicitation */
ICMP6_TYPE_MRS = 152,
/** Multicast router termination */
ICMP6_TYPE_MRT = 153,
/** Private experimentation */
ICMP6_TYPE_PE3 = 200,
/** Private experimentation */
ICMP6_TYPE_PE4 = 201,
/** Reserved for expansion of informational messages */
ICMP6_TYPE_RSV_INF = 255
};
/** ICMP destination unreachable codes */
enum icmp6_dur_code {
/** No route to destination */
ICMP6_DUR_NO_ROUTE = 0,
/** Communication with destination administratively prohibited */
ICMP6_DUR_PROHIBITED = 1,
/** Beyond scope of source address */
ICMP6_DUR_SCOPE = 2,
/** Address unreachable */
ICMP6_DUR_ADDRESS = 3,
/** Port unreachable */
ICMP6_DUR_PORT = 4,
/** Source address failed ingress/egress policy */
ICMP6_DUR_POLICY = 5,
/** Reject route to destination */
ICMP6_DUR_REJECT_ROUTE = 6
};
/** ICMP time exceeded codes */
enum icmp6_te_code {
/** Hop limit exceeded in transit */
ICMP6_TE_HL = 0,
/** Fragment reassembly time exceeded */
ICMP6_TE_FRAG = 1
};
/** ICMP parameter code */
enum icmp6_pp_code {
/** Erroneous header field encountered */
ICMP6_PP_FIELD = 0,
/** Unrecognized next header type encountered */
ICMP6_PP_HEADER = 1,
/** Unrecognized IPv6 option encountered */
ICMP6_PP_OPTION = 2
};
/** This is the standard ICMP6 header. */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"

View File

@@ -44,6 +44,22 @@
extern "C" {
#endif
/** This is the packed version of ip4_addr_t,
used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip4_addr_packed {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
typedef struct ip4_addr_packed ip4_addr_p_t;
/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */
#define IP_HLEN 20

View File

@@ -43,6 +43,21 @@
#ifdef __cplusplus
extern "C" {
#endif
/** This is the packed version of ip6_addr_t,
used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip6_addr_packed {
PACK_STRUCT_FIELD(u32_t addr[4]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
typedef struct ip6_addr_packed ip6_addr_p_t;
#define IP6_HLEN 40

View File

@@ -38,7 +38,7 @@
#define LWIP_HDR_PROT_MLD6_H
#include "lwip/arch.h"
#include "lwip/ip6_addr.h"
#include "lwip/prot/ip6.h"
#ifdef __cplusplus
extern "C" {

View File

@@ -39,6 +39,7 @@
#include "lwip/arch.h"
#include "lwip/ip6_addr.h"
#include "lwip/prot/ip6.h"
#ifdef __cplusplus
extern "C" {
@@ -246,6 +247,29 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
/** Recursive DNS Server Option. */
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS
#else
#define LWIP_RDNSS_OPTION_MAX_SERVERS 1
#endif
#define ND6_OPTION_TYPE_RDNSS (25)
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct rdnss_option {
PACK_STRUCT_FLD_8(u8_t type);
PACK_STRUCT_FLD_8(u8_t length);
PACK_STRUCT_FIELD(u16_t reserved);
PACK_STRUCT_FIELD(u32_t lifetime);
PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -85,7 +85,7 @@ PACK_STRUCT_END
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr))
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags))
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | (flags))
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags)))
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags))
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags))

View File

@@ -43,8 +43,6 @@
#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
#include <stddef.h> /* for size_t */
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#include "lwip/inet.h"

View File

@@ -34,44 +34,6 @@
* Author: Adam Dunkels <adam@sics.se>
*/
/**
* @defgroup sys_layer System abstraction layer
* @ingroup infrastructure
* @verbinclude "sys_arch.txt"
*
* @defgroup sys_os OS abstraction layer
* @ingroup sys_layer
* No need to implement functions in this section in NO_SYS mode.
*
* @defgroup sys_sem Semaphores
* @ingroup sys_os
*
* @defgroup sys_mutex Mutexes
* @ingroup sys_os
* Mutexes are recommended to correctly handle priority inversion,
* especially if you use LWIP_CORE_LOCKING .
*
* @defgroup sys_mbox Mailboxes
* @ingroup sys_os
*
* @defgroup sys_time Time
* @ingroup sys_layer
*
* @defgroup sys_prot Critical sections
* @ingroup sys_layer
* Used to protect short regions of code against concurrent access.
* - Your system is a bare-metal system (probably with an RTOS)
* and interrupts are under your control:
* Implement this as LockInterrupts() / UnlockInterrupts()
* - Your system uses an RTOS with deferred interrupt handling from a
* worker thread: Implement as a global mutex or lock/unlock scheduler
* - Your system uses a high-level OS with e.g. POSIX signals:
* Implement as a global mutex
*
* @defgroup sys_misc Misc
* @ingroup sys_os
*/
#ifndef LWIP_HDR_SYS_H
#define LWIP_HDR_SYS_H

View File

@@ -145,7 +145,7 @@ typedef u32_t tcpwnd_size_t;
typedef u16_t tcpwnd_size_t;
#endif
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS
typedef u16_t tcpflags_t;
#else
typedef u8_t tcpflags_t;
@@ -210,7 +210,7 @@ struct tcp_pcb {
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
#define TF_ACK_NOW 0x02U /* Immediate ACK. */
#define TF_INFR 0x04U /* In fast recovery. */
#define TF_TIMESTAMP 0x08U /* Timestamp option enabled */
#define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */
#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */
#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */
#define TF_NODELAY 0x40U /* Disable Nagle algorithm */
@@ -220,6 +220,9 @@ struct tcp_pcb {
#endif
#if TCP_LISTEN_BACKLOG
#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */
#endif
#if LWIP_TCP_TIMESTAMPS
#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */
#endif
/* the rest of the fields are in host byte order
@@ -358,7 +361,11 @@ void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);
#endif /* LWIP_CALLBACK_API */
void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
#if LWIP_TCP_TIMESTAMPS
#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
#else /* LWIP_TCP_TIMESTAMPS */
#define tcp_mss(pcb) ((pcb)->mss)
#endif /* LWIP_TCP_TIMESTAMPS */
#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf))
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
/** @ingroup tcp_raw */
@@ -387,6 +394,7 @@ err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port, tcp_connected_fn connected);
struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err);
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
/** @ingroup tcp_raw */
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)

View File

@@ -138,10 +138,10 @@
*/
struct link_callbacks {
/* Start a connection (e.g. Initiate discovery phase) */
err_t (*connect) (ppp_pcb *pcb, void *ctx);
void (*connect) (ppp_pcb *pcb, void *ctx);
#if PPP_SERVER
/* Listen for an incoming connection (Passive mode) */
err_t (*listen) (ppp_pcb *pcb, void *ctx);
void (*listen) (ppp_pcb *pcb, void *ctx);
#endif /* PPP_SERVER */
/* End a connection (i.e. initiate disconnect phase) */
void (*disconnect) (ppp_pcb *pcb, void *ctx);

View File

@@ -56,6 +56,10 @@
#include "netif/ppp/pppoe.h"
#endif /* PPPOE_SUPPORT */
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
const struct eth_addr ethzero = {{0,0,0,0,0,0}};

View File

@@ -616,7 +616,8 @@ lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
err_t
lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
{
s8_t i;
err_t result;
const u8_t *hwaddr;
struct ieee_802154_addr src, dest;
#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
ip6_addr_t ip6_src;
@@ -663,35 +664,23 @@ lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
}
#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
/* Get next hop record. */
i = nd6_get_next_hop_entry(ip6addr, netif);
if (i < 0) {
/* Ask ND6 what to do with the packet. */
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
if (result != ERR_OK) {
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
/* failed to get a next hop neighbor record. */
return ERR_MEM;
return result;
}
/* Now that we have a destination record, send or queue the packet. */
if (neighbor_cache[i].state == ND6_STALE) {
/* Switch to delay state. */
neighbor_cache[i].state = ND6_DELAY;
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
}
/* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
(neighbor_cache[i].state == ND6_DELAY) ||
(neighbor_cache[i].state == ND6_PROBE)) {
/* Send out. */
dest.addr_len = netif->hwaddr_len;
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, netif->hwaddr_len);
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
return lowpan6_frag(netif, q, &src, &dest);
/* If no hardware address is returned, nd6 has queued the packet for later. */
if (hwaddr == NULL) {
return ERR_OK;
}
/* We should queue packet on this interface. */
return nd6_queue_packet(i, q);
/* Send out the packet using the returned hardware address. */
dest.addr_len = netif->hwaddr_len;
SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len);
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
return lowpan6_frag(netif, q, &src, &dest);
}
static struct pbuf *

View File

@@ -275,8 +275,8 @@ err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) {
PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff));
if (holdoff == 0) {
new_phase(pcb, PPP_PHASE_INITIALIZE);
return pcb->link_cb->connect(pcb, pcb->link_ctx_cb);
ppp_do_connect(pcb);
return ERR_OK;
}
new_phase(pcb, PPP_PHASE_HOLDOFF);
@@ -302,7 +302,8 @@ err_t ppp_listen(ppp_pcb *pcb) {
if (pcb->link_cb->listen) {
new_phase(pcb, PPP_PHASE_INITIALIZE);
return pcb->link_cb->listen(pcb, pcb->link_ctx_cb);
pcb->link_cb->listen(pcb, pcb->link_ctx_cb);
return ERR_OK;
}
return ERR_IF;
}
@@ -1145,12 +1146,12 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
nsa = dns_getserver(0);
ip_addr_set_ip4_u32(&nsb, ns1);
if (ip_addr_cmp(nsa, &nsb)) {
dns_setserver(0, IP4_ADDR_ANY);
dns_setserver(0, IP_ADDR_ANY);
}
nsa = dns_getserver(1);
ip_addr_set_ip4_u32(&nsb, ns2);
if (ip_addr_cmp(nsa, &nsb)) {
dns_setserver(1, IP4_ADDR_ANY);
dns_setserver(1, IP_ADDR_ANY);
}
return 1;
}

View File

@@ -222,6 +222,7 @@ pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m)
msg->msg.msg.l2tpcreate.secret_len,
#else /* PPPOL2TP_AUTH_SUPPORT */
NULL,
0,
#endif /* PPPOL2TP_AUTH_SUPPORT */
msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb);
return ERR_OK;
@@ -239,6 +240,10 @@ pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipad
ppp_pcb* result;
PPPAPI_VAR_DECLARE(msg);
PPPAPI_VAR_ALLOC_RETURN_NULL(msg);
#if !PPPOL2TP_AUTH_SUPPORT
LWIP_UNUSED_ARG(secret);
LWIP_UNUSED_ARG(secret_len);
#endif /* !PPPOL2TP_AUTH_SUPPORT */
PPPAPI_VAR_REF(msg).msg.ppp = NULL;
PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif;

View File

@@ -119,7 +119,7 @@ LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_so
/* callbacks called from PPP core */
static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol);
static err_t pppoe_connect(ppp_pcb *ppp, void *ctx);
static void pppoe_connect(ppp_pcb *ppp, void *ctx);
static void pppoe_disconnect(ppp_pcb *ppp, void *ctx);
static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx);
@@ -879,7 +879,7 @@ pppoe_timeout(void *arg)
}
/* Start a connection (i.e. initiate discovery phase) */
static err_t
static void
pppoe_connect(ppp_pcb *ppp, void *ctx)
{
err_t err;
@@ -934,7 +934,6 @@ pppoe_connect(ppp_pcb *ppp, void *ctx)
PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
}
sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
return err;
}
/* disconnect */

View File

@@ -73,7 +73,7 @@ LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp
static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol);
static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */
static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */
static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */
static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */
/* Prototypes for procedures local to this file. */
@@ -113,6 +113,10 @@ ppp_pcb *pppol2tp_create(struct netif *pppif,
ppp_pcb *ppp;
pppol2tp_pcb *l2tp;
struct udp_pcb *udp;
#if !PPPOL2TP_AUTH_SUPPORT
LWIP_UNUSED_ARG(secret);
LWIP_UNUSED_ARG(secret_len);
#endif /* !PPPOL2TP_AUTH_SUPPORT */
if (ipaddr == NULL) {
goto ipaddr_check_failed;
@@ -251,7 +255,7 @@ static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) {
}
/* Be a LAC, connect to a LNS. */
static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
err_t err;
pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx;
lcp_options *lcp_wo;
@@ -303,7 +307,7 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
udp_bind(l2tp->udp, IP6_ADDR_ANY, 0);
} else
#endif /* LWIP_IPV6 */
udp_bind(l2tp->udp, IP4_ADDR_ANY, 0);
udp_bind(l2tp->udp, IP_ADDR_ANY, 0);
#if PPPOL2TP_AUTH_SUPPORT
/* Generate random vector */
@@ -322,7 +326,6 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err));
}
sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp);
return err;
}
/* Disconnect */

View File

@@ -35,8 +35,8 @@
#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */
#include <string.h>
#include <stddef.h>
#include "lwip/arch.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
@@ -57,9 +57,9 @@ LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "P
/* callbacks called from PPP core */
static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol);
static err_t pppos_connect(ppp_pcb *ppp, void *ctx);
static void pppos_connect(ppp_pcb *ppp, void *ctx);
#if PPP_SERVER
static err_t pppos_listen(ppp_pcb *ppp, void *ctx);
static void pppos_listen(ppp_pcb *ppp, void *ctx);
#endif /* PPP_SERVER */
static void pppos_disconnect(ppp_pcb *ppp, void *ctx);
static err_t pppos_destroy(ppp_pcb *ppp, void *ctx);
@@ -298,7 +298,7 @@ pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol)
return err;
}
static err_t
static void
pppos_connect(ppp_pcb *ppp, void *ctx)
{
pppos_pcb *pppos = (pppos_pcb *)ctx;
@@ -327,11 +327,10 @@ pppos_connect(ppp_pcb *ppp, void *ctx)
*/
PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num));
ppp_start(ppp); /* notify upper layers */
return ERR_OK;
}
#if PPP_SERVER
static err_t
static void
pppos_listen(ppp_pcb *ppp, void *ctx)
{
pppos_pcb *pppos = (pppos_pcb *)ctx;
@@ -360,7 +359,6 @@ pppos_listen(ppp_pcb *ppp, void *ctx)
*/
PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num));
ppp_start(ppp); /* notify upper layers */
return ERR_OK;
}
#endif /* PPP_SERVER */
@@ -471,18 +469,20 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l)
u8_t escaped;
PPPOS_DECL_PROTECT(lev);
PPPOS_PROTECT(lev);
if (!pppos->open) {
PPPOS_UNPROTECT(lev);
return;
}
PPPOS_UNPROTECT(lev);
PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
while (l-- > 0) {
cur_char = *s++;
PPPOS_PROTECT(lev);
/* ppp_input can disconnect the interface, we need to abort to prevent a memory
* leak if there are remaining bytes because pppos_connect and pppos_listen
* functions expect input buffer to be free. Furthermore there are no real
* reason to continue reading bytes if we are disconnected.
*/
if (!pppos->open) {
PPPOS_UNPROTECT(lev);
return;
}
escaped = ESCAPE_P(pppos->in_accm, cur_char);
PPPOS_UNPROTECT(lev);
/* Handle special characters. */

View File

@@ -247,11 +247,13 @@ int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) {
val = va_arg(args, unsigned int);
base = 16;
break;
#if 0 /* unused (and wrong on LLP64 systems) */
case 'p':
val = (unsigned long) va_arg(args, void *);
base = 16;
neg = 2;
break;
#endif /* unused (and wrong on LLP64 systems) */
case 's':
str = va_arg(args, char *);
break;

53
test/fuzz/Makefile Normal file
View File

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

Some files were not shown because too many files have changed in this diff Show More